(* Copyright 2012-2015 by Adam Petcher.				* * Use of this source code is governed by the license described	* * in the LICENSE file at the root of the source tree.		*)
Set Implicit Arguments.
Local Open Scope list_scope.
Notation "'query' v" := (OC_Query  _ v) (at level 79) : comp_scope.
Fixpoint oc_compMap(A B C D : Set)(eqdb : EqDec B)(c : A -> OracleComp C D B)(ls : list A) : OracleComp C D (list B) :=
match ls with
| nil => $ (ret nil)
| a :: ls' =>
b <--$ c a;
lsb' <--$ oc_compMap _ c ls';
$ (ret (b :: lsb'))
end.
induction ls1; inversion 1; subst; intuition; simpl in *.
comp_simp.
eapply comp_spec_ret; simpl; econstructor.
simpl.
comp_skip.
comp_simp.
comp_skip.
comp_simp.
eapply comp_spec_ret; intuition.
simpl.
econstructor; eauto.
Qed.
induction ls; intuition; simpl in *.
comp_simp.
eapply comp_spec_eq_refl.
comp_skip.
comp_skip.
comp_simp.
eapply comp_spec_eq_refl.
Qed.
induction ls; intuition; simpl in *.
comp_simp.
eapply comp_spec_ret; intuition.
inversion H; clear H; subst.
simpl; inline_first.
unfold randomFunc.
rewrite H0.
inline_first.
comp_skip.
comp_simp.
inline_first.
comp_skip.
comp_simp.
comp_skip.
eapply IHls; intuition.
simpl.
case_eq (eqb a0 a); intuition.
rewrite eqb_leibniz in H7.
subst.
intuition.
comp_simp.
simpl in *; subst.
eapply comp_spec_ret; intuition.
intuition.
Qed.
induction ls; intuition; simpl in *;
econstructor; wftac; intuition.
Qed.
induction lsa; intuition; simpl.
fcf_inline_first.
fcf_simp.
rewrite app_nil_r.
fcf_spec_ret.
fcf_inline_first.
fcf_skip.
eapply comp_spec_eq_trans.
eapply IHlsa.
fcf_inline_first.
fcf_skip.
fcf_inline_first.
fcf_simp.
rewrite <- app_assoc.
simpl.
fcf_spec_ret.
Qed.

Theorem compFold_oc_equiv :
forall (A B S : Set)(eqdb : EqDec B)(eqds : EqDec S)(O : S -> A -> Comp (B * S))(lsa : list A)(initS : S),
comp_spec eq
(compFold _
(fun (acc : list B * S) (d : A) =>
[rs, s]<-2 acc; z <-$ O s d; [r, s0]<-2 z; ret (rs ++ r :: nil, s0))
(nil, initS) lsa)
((oc_compMap _ (fun a : A => query a) lsa) S _ O initS).