12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091(**
This module contains a non-determinism monad.
*)moduleEnum=Batteries.Enum;;moduleLazyList=structtype'at='anodeLazy.tand'anode=Nil|Consof'a*'at;;letempty:'at=Lazy.from_valNil;;letsingleton(x:'a):'at=Lazy.from_val(Cons(x,empty));;letrecmap(f:'a->'b)(xs:'at):'bt=letmapper(node:'anode):'bnode=matchnodewith|Nil->Nil|Cons(x,xs')->Cons(fx,mapfxs')inlazy(mapper(Lazy.forcexs))letappend(xs:'at)(ys:'at):'at=letrecappend'(xs:'at)(ys:'at):'anode=matchLazy.forcexswith|Nil->Lazy.forceys|Cons(x,xs')->Cons(x,lazy(append'xs'ys))inlazy(append'xsys);;letrecconcat(xss:'att):'at=letconcat'(xss:'att):'anode=matchLazy.forcexsswith|Nil->Nil|Cons(xs,xss')->Lazy.force(appendxs(concatxss'))inlazy(concat'xss);;letconcat_map(f:'a->'bt)(xs:'at):'bt=concat(mapfxs);;letof_enum(e:'aEnum.t):'at=letrecof_enum'():'anode=matchEnum.getewith|None->Nil|Somex->Cons(x,lazy(of_enum'()))inLazy.from_funof_enum';;letenum(xs:'at):'aEnum.t=letunfolder(xs:'at):('a*'at)option=matchLazy.forcexswith|Nil->None|Cons(x,xs')->Some(x,xs')inEnum.unfoldxsunfolder;;letof_list(xs:'alist):'at=xs|>BatList.enum|>of_enum;;end;;moduletypeNondeterminism_monad_sig=sigtype'amincludeMonads.MonadPluswithtype'am:='amincludeMonads.Utilswithtype'am:='amvalpick_enum:'aEnum.t->'amvalenum:'am->'aEnum.tvalstop_unless:bool->unitmvalempty:unit->'amvalalternative:'am->'am->'amend;;moduleNondeterminism_monad:Nondeterminism_monad_sig=structmoduleBase=structtype'am='aLazyList.t;;letpurex=LazyList.singletonx;;letbindxf=LazyList.concat_mapfx;;letzero()=LazyList.empty;;letplus=LazyList.append;;end;;includeBase;;includeMonads.MakeUtils(Base);;letpick_enum=LazyList.of_enum;;letenum=LazyList.enum;;letstop_unlessx=ifxthenreturn()elsezero();;letempty()=LazyList.empty;;letalternativexy=LazyList.concat@@LazyList.of_list[x;y];;end;;