123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545(** Applicatives model computations in which values computed by subcomputations cannot
affect what subsequent computations will take place.
Relative to monads, this restriction takes power away from the user of the interface
and gives it to the implementation. In particular, because the structure of the
entire computation is known, one can augment its definition with some description of
that structure.
For more information, see:
{v
Applicative Programming with Effects.
Conor McBride and Ross Paterson.
Journal of Functional Programming 18:1 (2008), pages 1-13.
http://staff.city.ac.uk/~ross/papers/Applicative.pdf
v} *)open!ImportmoduletypeBasic=sigtype'atvalreturn:'a->'atvalapply:('a->'b)t->'at->'bt(** The following identities ought to hold for every Applicative (for some value of =):
- identity: [return Fn.id <*> t = t]
- composition: [return Fn.compose <*> tf <*> tg <*> tx = tf <*> (tg <*> tx)]
- homomorphism: [return f <*> return x = return (f x)]
- interchange: [tf <*> return x = return (fun f -> f x) <*> tf]
Note: <*> is the infix notation for apply. *)(** The [map] argument to [Applicative.Make] says how to implement the applicative's
[map] function. [`Define_using_apply] means to define [map t ~f = return f <*> t].
[`Custom] overrides the default implementation, presumably with something more
efficient.
Some other functions returned by [Applicative.Make] are defined in terms of [map],
so passing in a more efficient [map] will improve their efficiency as well. *)valmap:[`Define_using_apply|`Customof'at->f:('a->'b)->'bt]end(** Similar to [Basic], with the same laws, and the additional requirement that ['a t]
can be mapped with a local function. *)moduletypeBasic_local=sigtype'atvalreturn:'a->'atvalapply:('a->'b)t->'at->'btvalmap:'at->f:(('a->'b)[@local])->'btendmoduletypeBasic_using_map2=sigtype'atvalreturn:'a->'atvalmap2:'at->'bt->f:('a->'b->'c)->'ctvalmap:[`Define_using_map2|`Customof'at->f:('a->'b)->'bt]endmoduletypeBasic_using_map2_local=sigtype'atvalreturn:'a->'atvalmap2:'at->'bt->f:(('a->'b->'c)[@local])->'ctvalmap:[`Define_using_map2|`Customof'at->f:(('a->'b)[@local])->'bt]endmoduletypeApplicative_infix_gen=sigtype'attype('a,'b)fn(** same as [apply] *)val(<*>):('a->'b)t->'at->'btval(<*):'at->unitt->'atval(*>):unitt->'at->'atval(>>|):'at->('a->'b,'bt)fnendmoduletypeApplicative_infix=Applicative_infix_genwithtype('a,'b)fn:='a->'bmoduletypeApplicative_infix_local=Applicative_infix_genwithtype('a,'b)fn:=('a[@local])->'bmoduletypeFor_let_syntax_gen=sigtype'attype('a,'b)fntype('a,'b)f_labeled_fnvalreturn:'a->'atvalmap:'at->('a->'b,'bt)f_labeled_fnvalboth:'at->'bt->('a*'b)tincludeApplicative_infix_genwithtype'at:='atandtype('a,'b)fn:=('a,'b)fnendmoduletypeFor_let_syntax=For_let_syntax_genwithtype('a,'b)fn:='a->'bandtype('a,'b)f_labeled_fn:=f:'a->'bmoduletypeFor_let_syntax_local=For_let_syntax_genwithtype('a,'b)fn:=('a[@local])->'bandtype('a,'b)f_labeled_fn:=f:('a[@local])->'bmoduletypeS_gen=sigincludeFor_let_syntax_gentype('a,'b,'c)fun2type('a,'b,'c,'d)fun3valapply:('a->'b)t->'at->'btvalmap2:'at->'bt->(('a,'b,'c)fun2,'ct)f_labeled_fnvalmap3:'at->'bt->'ct->(('a,'b,'c,'d)fun3,'dt)f_labeled_fnvalall:'atlist->'alisttvalall_unit:unittlist->unittmoduleApplicative_infix:Applicative_infix_genwithtype'at:='atandtype('a,'b)fn:=('a,'b)fnendmoduletypeS=S_genwithtype('a,'b)fn:='a->'bandtype('a,'b)f_labeled_fn:=f:'a->'bandtype('a,'b,'c)fun2:='a->'b->'candtype('a,'b,'c,'d)fun3:='a->'b->'c->'dmoduletypeS_local=S_genwithtype('a,'b)fn:=('a[@local])->'bandtype('a,'b)f_labeled_fn:=f:('a[@local])->'bandtype('a,'b,'c)fun2:='a->(('b->'c)[@local])andtype('a,'b,'c,'d)fun3:='a->(('b->(('c->'d)[@local]))[@local])moduletypeLet_syntax=sigtype'atmoduleOpen_on_rhs_intf:sigmoduletypeSendmoduleLet_syntax:sigvalreturn:'a->'atincludeApplicative_infixwithtype'at:='atmoduleLet_syntax:sigvalreturn:'a->'atvalmap:'at->f:('a->'b)->'btvalboth:'at->'bt->('a*'b)tmoduleOpen_on_rhs:Open_on_rhs_intf.SendendendmoduletypeBasic2=sigtype('a,'e)tvalreturn:'a->('a,_)tvalapply:('a->'b,'e)t->('a,'e)t->('b,'e)tvalmap:[`Define_using_apply|`Customof('a,'e)t->f:('a->'b)->('b,'e)t]endmoduletypeBasic2_local=sigtype('a,'e)tvalreturn:'a->('a,_)tvalapply:('a->'b,'e)t->('a,'e)t->('b,'e)tvalmap:('a,'e)t->f:(('a->'b)[@local])->('b,'e)tendmoduletypeBasic2_using_map2=sigtype('a,'e)tvalreturn:'a->('a,_)tvalmap2:('a,'e)t->('b,'e)t->f:('a->'b->'c)->('c,'e)tvalmap:[`Define_using_map2|`Customof('a,'e)t->f:('a->'b)->('b,'e)t]endmoduletypeBasic2_using_map2_local=sigtype('a,'e)tvalreturn:'a->('a,_)tvalmap2:('a,'e)t->('b,'e)t->f:(('a->'b->'c)[@local])->('c,'e)tvalmap:[`Define_using_map2|`Customof('a,'e)t->f:(('a->'b)[@local])->('b,'e)t]endmoduletypeApplicative_infix2_gen=sigtype('a,'e)ttype('a,'b)fnval(<*>):('a->'b,'e)t->('a,'e)t->('b,'e)tval(<*):('a,'e)t->(unit,'e)t->('a,'e)tval(*>):(unit,'e)t->('a,'e)t->('a,'e)tval(>>|):('a,'e)t->('a->'b,('b,'e)t)fnendmoduletypeApplicative_infix2=Applicative_infix2_genwithtype('a,'b)fn:='a->'bmoduletypeApplicative_infix2_local=Applicative_infix2_genwithtype('a,'b)fn:=('a[@local])->'bmoduletypeFor_let_syntax2_gen=sigtype('a,'e)ttype('a,'b)fntype('a,'b)f_labeled_fnvalreturn:'a->('a,_)tvalmap:('a,'e)t->('a->'b,('b,'e)t)f_labeled_fnvalboth:('a,'e)t->('b,'e)t->('a*'b,'e)tincludeApplicative_infix2_genwithtype('a,'e)t:=('a,'e)tandtype('a,'b)fn:=('a,'b)fnendmoduletypeFor_let_syntax2=For_let_syntax2_genwithtype('a,'b)fn:='a->'bandtype('a,'b)f_labeled_fn:=f:'a->'bmoduletypeFor_let_syntax2_local=For_let_syntax2_genwithtype('a,'b)fn:=('a[@local])->'bandtype('a,'b)f_labeled_fn:=f:('a[@local])->'bmoduletypeS2_gen=sigincludeFor_let_syntax2_gentype('a,'b,'c)fun2type('a,'b,'c,'d)fun3valapply:('a->'b,'e)t->('a,'e)t->('b,'e)tvalmap2:('a,'e)t->('b,'e)t->(('a,'b,'c)fun2,('c,'e)t)f_labeled_fnvalmap3:('a,'e)t->('b,'e)t->('c,'e)t->(('a,'b,'c,'d)fun3,('d,'e)t)f_labeled_fnvalall:('a,'e)tlist->('alist,'e)tvalall_unit:(unit,'e)tlist->(unit,'e)tmoduleApplicative_infix:Applicative_infix2_genwithtype('a,'e)t:=('a,'e)tandtype('a,'b)fn:=('a,'b)fnendmoduletypeS2=S2_genwithtype('a,'b)fn:='a->'bandtype('a,'b)f_labeled_fn:=f:'a->'bandtype('a,'b,'c)fun2:='a->'b->'candtype('a,'b,'c,'d)fun3:='a->'b->'c->'dmoduletypeS2_local=S2_genwithtype('a,'b)fn:=('a[@local])->'bandtype('a,'b)f_labeled_fn:=f:('a[@local])->'bandtype('a,'b,'c)fun2:='a->(('b->'c)[@local])andtype('a,'b,'c,'d)fun3:='a->(('b->(('c->'d)[@local]))[@local])moduletypeLet_syntax2=sigtype('a,'e)tmoduleOpen_on_rhs_intf:sigmoduletypeSendmoduleLet_syntax:sigvalreturn:'a->('a,_)tincludeApplicative_infix2withtype('a,'e)t:=('a,'e)tmoduleLet_syntax:sigvalreturn:'a->('a,_)tvalmap:('a,'e)t->f:('a->'b)->('b,'e)tvalboth:('a,'e)t->('b,'e)t->('a*'b,'e)tmoduleOpen_on_rhs:Open_on_rhs_intf.SendendendmoduletypeBasic3=sigtype('a,'d,'e)tvalreturn:'a->('a,_,_)tvalapply:('a->'b,'d,'e)t->('a,'d,'e)t->('b,'d,'e)tvalmap:[`Define_using_apply|`Customof('a,'d,'e)t->f:('a->'b)->('b,'d,'e)t]endmoduletypeBasic3_using_map2=sigtype('a,'d,'e)tvalreturn:'a->('a,_,_)tvalmap2:('a,'d,'e)t->('b,'d,'e)t->f:('a->'b->'c)->('c,'d,'e)tvalmap:[`Define_using_map2|`Customof('a,'d,'e)t->f:('a->'b)->('b,'d,'e)t]endmoduletypeBasic3_using_map2_local=sigtype('a,'d,'e)tvalreturn:'a->('a,_,_)tvalmap2:('a,'d,'e)t->('b,'d,'e)t->f:(('a->'b->'c)[@local])->('c,'d,'e)tvalmap:[`Define_using_map2|`Customof('a,'d,'e)t->f:(('a->'b)[@local])->('b,'d,'e)t]endmoduletypeApplicative_infix3_gen=sigtype('a,'d,'e)ttype('a,'b)fnval(<*>):('a->'b,'d,'e)t->('a,'d,'e)t->('b,'d,'e)tval(<*):('a,'d,'e)t->(unit,'d,'e)t->('a,'d,'e)tval(*>):(unit,'d,'e)t->('a,'d,'e)t->('a,'d,'e)tval(>>|):('a,'d,'e)t->('a->'b,('b,'d,'e)t)fnendmoduletypeApplicative_infix3=Applicative_infix3_genwithtype('a,'b)fn:='a->'bmoduletypeApplicative_infix3_local=Applicative_infix3_genwithtype('a,'b)fn:=('a[@local])->'bmoduletypeFor_let_syntax3_gen=sigtype('a,'d,'e)ttype('a,'b)fntype('a,'b)f_labeled_fnvalreturn:'a->('a,_,_)tvalmap:('a,'d,'e)t->('a->'b,('b,'d,'e)t)f_labeled_fnvalboth:('a,'d,'e)t->('b,'d,'e)t->('a*'b,'d,'e)tincludeApplicative_infix3_genwithtype('a,'d,'e)t:=('a,'d,'e)tandtype('a,'b)fn:=('a,'b)fnendmoduletypeFor_let_syntax3=For_let_syntax3_genwithtype('a,'b)fn:='a->'bandtype('a,'b)f_labeled_fn:=f:'a->'bmoduletypeFor_let_syntax3_local=For_let_syntax3_genwithtype('a,'b)fn:=('a[@local])->'bandtype('a,'b)f_labeled_fn:=f:('a[@local])->'bmoduletypeS3_gen=sigincludeFor_let_syntax3_gentype('a,'b,'c)fun2type('a,'b,'c,'d)fun3valapply:('a->'b,'d,'e)t->('a,'d,'e)t->('b,'d,'e)tvalmap2:('a,'d,'e)t->('b,'d,'e)t->(('a,'b,'c)fun2,('c,'d,'e)t)f_labeled_fnvalmap3:('a,'d,'e)t->('b,'d,'e)t->('c,'d,'e)t->(('a,'b,'c,'result)fun3,('result,'d,'e)t)f_labeled_fnvalall:('a,'d,'e)tlist->('alist,'d,'e)tvalall_unit:(unit,'d,'e)tlist->(unit,'d,'e)tmoduleApplicative_infix:Applicative_infix3_genwithtype('a,'d,'e)t:=('a,'d,'e)tandtype('a,'b)fn:=('a,'b)fnendmoduletypeS3=S3_genwithtype('a,'b)fn:='a->'bandtype('a,'b)f_labeled_fn:=f:'a->'bandtype('a,'b,'c)fun2:='a->'b->'candtype('a,'b,'c,'d)fun3:='a->'b->'c->'dmoduletypeS3_local=S3_genwithtype('a,'b)fn:=('a[@local])->'bandtype('a,'b)f_labeled_fn:=f:('a[@local])->'bandtype('a,'b,'c)fun2:='a->(('b->'c)[@local])andtype('a,'b,'c,'d)fun3:='a->(('b->(('c->'d)[@local]))[@local])moduletypeLet_syntax3=sigtype('a,'d,'e)tmoduleOpen_on_rhs_intf:sigmoduletypeSendmoduleLet_syntax:sigvalreturn:'a->('a,_,_)tincludeApplicative_infix3withtype('a,'d,'e)t:=('a,'d,'e)tmoduleLet_syntax:sigvalreturn:'a->('a,_,_)tvalmap:('a,'d,'e)t->f:('a->'b)->('b,'d,'e)tvalboth:('a,'d,'e)t->('b,'d,'e)t->('a*'b,'d,'e)tmoduleOpen_on_rhs:Open_on_rhs_intf.Sendendend(** [Lazy_applicative] is an applicative whose structure may be computed on-demand,
instead of being constructed up-front. This is useful when implementing traversals
over large data structures, where otherwise we have to pay O(n) up-front cost both
in time and in memory. *)moduletypeLazy_applicative=sigincludeSvalof_thunk:(unit->'at)->'atendmoduletypeApplicative=sigmoduletypeApplicative_infix=Applicative_infixmoduletypeApplicative_infix2=Applicative_infix2moduletypeApplicative_infix3=Applicative_infix3moduletypeApplicative_infix_local=Applicative_infix_localmoduletypeApplicative_infix2_local=Applicative_infix2_localmoduletypeBasic=BasicmoduletypeBasic2=Basic2moduletypeBasic3=Basic3moduletypeBasic_local=Basic_localmoduletypeBasic2_local=Basic2_localmoduletypeBasic_using_map2=Basic_using_map2moduletypeBasic2_using_map2=Basic2_using_map2moduletypeBasic3_using_map2=Basic3_using_map2moduletypeBasic_using_map2_local=Basic_using_map2_localmoduletypeBasic2_using_map2_local=Basic2_using_map2_localmoduletypeBasic3_using_map2_local=Basic3_using_map2_localmoduletypeLet_syntax=Let_syntaxmoduletypeLet_syntax2=Let_syntax2moduletypeLet_syntax3=Let_syntax3moduletypeS=SmoduletypeS2=S2moduletypeS3=S3moduletypeLazy_applicative=Lazy_applicativemoduletypeS_local=S_localmoduletypeS2_local=S2_localmoduleS2_to_S(T:T.T)(X:S2):Swithtype'at=('a,T.t)X.tmoduleS_to_S2(X:S):S2withtype('a,'e)t='aX.tmoduleS3_to_S2(T:T.T)(X:S3):S2withtype('a,'d)t=('a,'d,T.t)X.tmoduleS3_to_S(T1:T.T)(T2:T.T)(X:S3):Swithtype'at=('a,T1.t,T2.t)X.tmoduleS2_to_S3(X:S2):S3withtype('a,'d,'e)t=('a,'d)X.tmoduleMake(X:Basic):Swithtype'at:='aX.tmoduleMake2(X:Basic2):S2withtype('a,'e)t:=('a,'e)X.tmoduleMake3(X:Basic3):S3withtype('a,'d,'e)t:=('a,'d,'e)X.tmoduleMake_let_syntax(X:For_let_syntax)(Intf:sigmoduletypeSend)(Impl:Intf.S):Let_syntaxwithtype'at:='aX.twithmoduleOpen_on_rhs_intf:=IntfmoduleMake_let_syntax2(X:For_let_syntax2)(Intf:sigmoduletypeSend)(Impl:Intf.S):Let_syntax2withtype('a,'e)t:=('a,'e)X.twithmoduleOpen_on_rhs_intf:=IntfmoduleMake_let_syntax3(X:For_let_syntax3)(Intf:sigmoduletypeSend)(Impl:Intf.S):Let_syntax3withtype('a,'d,'e)t:=('a,'d,'e)X.twithmoduleOpen_on_rhs_intf:=IntfmoduleMake_using_map2(X:Basic_using_map2):Swithtype'at:='aX.tmoduleMake2_using_map2(X:Basic2_using_map2):S2withtype('a,'e)t:=('a,'e)X.tmoduleMake3_using_map2(X:Basic3_using_map2):S3withtype('a,'d,'e)t:=('a,'d,'e)X.tmoduleMake_using_map2_local(X:Basic_using_map2_local):S_localwithtype'at:='aX.tmoduleMake2_using_map2_local(X:Basic2_using_map2_local):S2_localwithtype('a,'e)t:=('a,'e)X.tmoduleMake3_using_map2_local(X:Basic3_using_map2_local):S3_localwithtype('a,'d,'e)t:=('a,'d,'e)X.t(** The following functors give a sense of what Applicatives one can define.
Of these, [Of_monad] is likely the most useful. The others are mostly didactic. *)(** Every monad is Applicative via:
{[
let apply mf mx =
mf >>= fun f ->
mx >>| fun x ->
f x
]} *)moduleOf_monad(M:Monad.S):Swithtype'at:='aM.tmoduleOf_monad2(M:Monad.S2):S2withtype('a,'e)t:=('a,'e)M.tmoduleCompose(F:S)(G:S):Swithtype'at='aF.tG.tmodulePair(F:S)(G:S):Swithtype'at='aF.t*'aG.tend