123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213open!ImportmoduleArray=Array0moduleList=List0includeContainer_intfletwith_return=With_return.with_returntype('t,'a,'accum)fold='t->init:'accum->f:('accum->'a->'accum)->'accumtype('t,'a)iter='t->f:('a->unit)->unittype'tlength='t->intletiter~foldt~f=foldt~init:()~f:(fun()a->fa)letcount~foldt~f=foldt~init:0~f:(funna->iffathenn+1elsen)letsum(typea)~fold(moduleM:Summablewithtypet=a)t~f=foldt~init:M.zero~f:(funna->M.(+)n(fa));;letfold_result~fold~init~ft=with_return(fun{return}->Result.Ok(foldt~init~f:(funaccitem->matchfaccitemwith|Result.Okx->x|Error_ase->returne)));;letfold_until~fold~init~f~finisht=with_return(fun{return}->finish(foldt~init~f:(funaccitem->matchfaccitemwith|Continue_or_stop.Continuex->x|Stopx->returnx)));;letmin_elt~foldt~compare=foldt~init:None~f:(funaccelt->matchaccwith|None->Someelt|Somemin->ifcompareminelt>0thenSomeeltelseacc);;letmax_elt~foldt~compare=foldt~init:None~f:(funaccelt->matchaccwith|None->Someelt|Somemax->ifcomparemaxelt<0thenSomeeltelseacc);;letlength~foldc=foldc~init:0~f:(funacc_->acc+1)letis_empty~iterc=with_return(funr->iterc~f:(fun_->r.returnfalse);true);;letexists~iterc~f=with_return(funr->iterc~f:(funx->iffxthenr.returntrue);false);;letfor_all~iterc~f=with_return(funr->iterc~f:(funx->ifnot(fx)thenr.returnfalse);true);;letfind_map~itert~f=with_return(funr->itert~f:(funx->matchfxwith|None->()|Some_asres->r.returnres);None);;letfind~iterc~f=with_return(funr->iterc~f:(funx->iffxthenr.return(Somex));None);;letto_list~foldc=List.rev(foldc~init:[]~f:(funaccx->x::acc))letto_array~length~iterc=letarray=ref[||]inleti=ref0initerc~f:(funx->if!i=0thenarray:=Array.create~len:(lengthc)x;!array.(!i)<-x;incri);!array;;moduleMake_gen(T:Make_gen_arg):sigincludeGenericwithtype'at:='aT.twithtype'aelt:='aT.eltend=structletfold=T.foldletiter=matchT.iterwith|`Customiter->iter|`Define_using_fold->funt~f->iter~foldt~f;;letlength=matchT.lengthwith|`Customlength->length|`Define_using_fold->funt->length~foldt;;letis_emptyt=is_empty~itertletsummt=sum~foldmtletcountt~f=count~foldt~fletexistst~f=exists~itert~fletfor_allt~f=for_all~itert~fletfind_mapt~f=find_map~itert~fletfindt~f=find~itert~fletto_listt=to_list~foldtletto_arrayt=to_array~length~itertletmin_eltt~compare=min_elt~foldt~compareletmax_eltt~compare=max_elt~foldt~compareletfold_resultt~init~f=fold_resultt~fold~init~fletfold_untilt~init~f~finish=fold_untilt~fold~init~f~finishendmoduleMake(T:Make_arg)=structincludeMake_gen(structincludeTtype'aelt='aend)letmemta~equal=existst~f:(equala)endmoduleMake0(T:Make0_arg)=structincludeMake_gen(structinclude(T:Make0_argwithtypet:=T.twithmoduleElt:=T.Elt)type'at=T.ttype'aelt=T.Elt.tend)letmemtelt=existst~f:(T.Elt.equalelt)endopenT(* The following functors exist as a consistency check among all the various [S?]
interfaces. They ensure that each particular [S?] is an instance of a more generic
signature. *)moduleCheck(T:T1)(Elt:T1)(M:Genericwithtype'at:='aT.twithtype'aelt:='aElt.t)=structendmoduleCheck_S0(M:S0)=Check(structtype'at=M.tend)(structtype'at=M.eltend)(M)moduleCheck_S0_phantom(M:S0_phantom)=Check(structtype'at='aM.tend)(structtype'at=M.eltend)(M)moduleCheck_S1(M:S1)=Check(structtype'at='aM.tend)(structtype'at='aend)(M)typephantommoduleCheck_S1_phantom(M:S1_phantom)=Check(structtype'at=('a,phantom)M.tend)(structtype'at='aend)(M)moduleCheck_S1_phantom_invariant(M:S1_phantom_invariant)=Check(structtype'at=('a,phantom)M.tend)(structtype'at='aend)(M)