123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170(************************************************************************)(* * The Coq Proof Assistant / The Coq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)(** Combinators on monadic computations. *)(** A definition of monads, each of the combinators is used in the
[Make] functor. *)moduletypeDef=sigtype+'atvalreturn:'a->'atval(>>=):'at->('a->'bt)->'btval(>>):unitt->'at->'atvalmap:('a->'b)->'at->'bt(** The monadic laws must hold:
- [(x>>=f)>>=g] = [x>>=fun x' -> (f x'>>=g)]
- [return a >>= f] = [f a]
- [x>>=return] = [x]
As well as the following identities:
- [x >> y] = [x >>= fun () -> y]
- [map f x] = [x >>= fun x' -> f x'] *)endmoduletypeListS=sigtype'at(** [List.map f l] maps [f] on the elements of [l] in left to right
order. *)valmap:('a->'bt)->'alist->'blistt(** [List.map f l] maps [f] on the elements of [l] in right to left
order. *)valmap_right:('a->'bt)->'alist->'blistt(** Like the regular [List.fold_right]. The monadic effects are
threaded right to left.
Note: many monads behave poorly with right-to-left order. For
instance a failure monad would still have to traverse the
whole list in order to fail and failure needs to be propagated
through the rest of the list in binds which are now
spurious. It is also the worst case for substitution monads
(aka free monads), exposing the quadratic behaviour.*)valfold_right:('a->'b->'bt)->'alist->'b->'bt(** Like the regular [List.fold_left]. The monadic effects are
threaded left to right. It is tail-recursive if the [(>>=)]
operator calls its second argument in a tail position. *)valfold_left:('a->'b->'at)->'a->'blist->'at(** Like the regular [List.iter]. The monadic effects are threaded
left to right. It is tail-recurisve if the [>>] operator calls
its second argument in a tail position. *)valiter:('a->unitt)->'alist->unitt(** Like the regular {!CList.map_filter}. The monadic effects are threaded left*)valmap_filter:('a->'boptiont)->'alist->'blistt(** {6 Two-list iterators} *)(** [fold_left2 r f s l1 l2] behaves like {!fold_left} but acts
simultaneously on two lists. Runs [r] (presumably an
exception-raising computation) if both lists do not have the
same length. *)valfold_left2:'at->('a->'b->'c->'at)->'a->'blist->'clist->'atendmoduletypeS=sigincludeDef(** List combinators *)moduleList:ListSwithtype'at:='atendmoduleMake(M:Def):Swithtype+'at='aM.t=structincludeMmoduleList=struct(* The combinators are loop-unrolled to spare a some monadic binds
(it is a common optimisation to treat the last of a list of
bind specially) and hopefully gain some efficiency using fewer
jump. *)letrecmapf=function|[]->return[]|[a]->M.map(funa'->[a'])(fa)|a::b::l->fa>>=funa'->fb>>=funb'->M.map(funl'->a'::b'::l')(mapfl)letrecmap_rightf=function|[]->return[]|[a]->M.map(funa'->[a'])(fa)|a::b::l->map_rightfl>>=funl'->fb>>=funb'->M.map(funa'->a'::b'::l')(fa)letrecfold_rightflx=matchlwith|[]->returnx|[a]->fax|a::b::l->fold_rightflx>>=funacc->fbacc>>=funacc->faaccletrecfold_leftfx=function|[]->returnx|[a]->fxa|a::b::l->fxa>>=funx'->fx'b>>=funx''->fold_leftfx''lletreciterf=function|[]->return()|[a]->fa|a::b::l->fa>>fb>>iterflletrecmap_filterf=function|[]->return[]|a::l->fa>>=function|None->map_filterfl|Someb->map_filterfl>>=funfiltered->return(b::filtered)letrecfold_left2rfxl1l2=matchl1,l2with|[],[]->returnx|[a],[b]->fxab|a1::a2::l1,b1::b2::l2->fxa1b1>>=funx'->fx'a2b2>>=funx''->fold_left2rfx''l1l2|_,_->rendend