123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611(* This file is free software, part of containers. See file "license" for more details. *)type'aiter=('a->unit)->unittype'agen=unit->'aoptiontype'aequal='a->'a->booltype'aord='a->'a->inttype'aprinter=Format.formatter->'a->unitincludeSeqletnil()=Nilletconsab()=Cons(a,b)letempty=nilletsingletonx()=Cons(x,nil)letinitnf=letrecauxi()=ifi>=nthenNilelseCons(fi,aux(i+1))inaux0letrec_foreverx()=Cons(x,_foreverx)letrec_repeatnx()=ifn<=0thenNilelseCons(x,_repeat(n-1)x)letrepeat?nx=matchnwith|None->_foreverx|Somen->_repeatnxletrecforeverf()=Cons(f(),foreverf)letis_emptyl=matchl()with|Nil->true|Cons_->falselethead_exnl=matchl()with|Nil->raiseNot_found|Cons(x,_)->xletheadl=matchl()with|Nil->None|Cons(x,_)->Somexlettail_exnl=matchl()with|Nil->raiseNot_found|Cons(_,l)->llettaill=matchl()with|Nil->None|Cons(_,l)->Somelletunconsl=matchl()with|Nil->None|Cons(h,t)->Some(h,t)letrecequaleql1l2=matchl1(),l2()with|Nil,Nil->true|Nil,_|_,Nil->false|Cons(x1,l1'),Cons(x2,l2')->eqx1x2&&equaleql1'l2'letreccomparecmpl1l2=matchl1(),l2()with|Nil,Nil->0|Nil,_->-1|_,Nil->1|Cons(x1,l1'),Cons(x2,l2')->letc=cmpx1x2inifc=0thencomparecmpl1'l2'elsecletrecfoldfaccres=matchres()with|Nil->acc|Cons(s,cont)->foldf(faccs)contletfold_left=foldletfoldifaccres=letrecauxaccires=matchres()with|Nil->acc|Cons(s,cont)->aux(faccis)(i+1)continauxacc0resletfold_lefti=foldiletreciterfl=matchl()with|Nil->()|Cons(x,l')->fx;iterfl'letiterifl=letrecauxfli=matchl()with|Nil->()|Cons(x,l')->fix;auxfl'(i+1)inauxfl0letlengthl=fold(funacc_->acc+1)0lletrectaken(l:'at)()=ifn=0thenNilelse(matchl()with|Nil->Nil|Cons(x,l')->Cons(x,take(n-1)l'))letrectake_whilepl()=matchl()with|Nil->Nil|Cons(x,l')->ifpxthenCons(x,take_whilepl')elseNilletrecdropn(l:'at)()=matchl()with|l'whenn=0->l'|Nil->Nil|Cons(_,l')->drop(n-1)l'()letrecdrop_whilepl()=matchl()with|Nil->Nil|Cons(x,l')whenpx->drop_whilepl'()|Cons_asres->resletrecmapfl()=matchl()with|Nil->Nil|Cons(x,l')->Cons(fx,mapfl')letmapifl=letrecauxfli()=matchl()with|Nil->Nil|Cons(x,tl)->Cons(fix,auxftl(i+1))inauxfl0letrecfmapf(l:'at)()=matchl()with|Nil->Nil|Cons(x,l')->(matchfxwith|None->fmapfl'()|Somey->Cons(y,fmapfl'))letrecfilterpl()=matchl()with|Nil->Nil|Cons(x,l')->ifpxthenCons(x,filterpl')elsefilterpl'()letrecappendl1l2()=matchl1()with|Nil->l2()|Cons(x,l1')->Cons(x,appendl1'l2)letreccyclel()=appendl(cyclel)()letreciteratefa()=Cons(a,iteratef(fa))letrecunfoldfacc()=matchfaccwith|None->Nil|Some(x,acc')->Cons(x,unfoldfacc')letrecfor_allpl=matchl()with|Nil->true|Cons(x,tl)->px&&for_allptlletrecexistspl=matchl()with|Nil->false|Cons(x,tl)->px||existsptlletrecfindpl=matchl()with|Nil->None|Cons(x,tl)->ifpxthenSomexelsefindptlletrecfind_mapfl=matchl()with|Nil->None|Cons(x,tl)->(matchfxwith|None->find_mapftl|e->e)letrecscanfaccres()=Cons(acc,fun()->matchres()with|Nil->Nil|Cons(s,cont)->scanf(faccs)cont())letrecflat_mapfl()=matchl()with|Nil->Nil|Cons(x,l')->_flat_map_appf(fx)l'()and_flat_map_appfll'()=matchl()with|Nil->flat_mapfl'()|Cons(x,tl)->Cons(x,_flat_map_appftll')letconcat_map=flat_mapletproduct_withfl1l2=letrec_next_lefth1tl1h2tl2()=matchtl1()with|Nil->_next_right~die:trueh1tl1h2tl2()|Cons(x,tl1')->_map_list_leftxh2(_next_right~die:false(x::h1)tl1'h2tl2)()and_next_right~dieh1tl1h2tl2()=matchtl2()with|Nilwhendie->Nil|Nil->_next_lefth1tl1h2tl2()|Cons(y,tl2')->_map_list_righth1y(_next_lefth1tl1(y::h2)tl2')()and_map_list_leftxlkont()=matchlwith|[]->kont()|y::l'->Cons(fxy,_map_list_leftxl'kont)and_map_list_rightlykont()=matchlwith|[]->kont()|x::l'->Cons(fxy,_map_list_rightl'ykont)in_next_left[]l1[]l2letmap_product=product_withletproductl1l2=product_with(funxy->x,y)l1l2letrecgroupeql()=matchl()with|Nil->Nil|Cons(x,l')->Cons(consx(take_while(eqx)l'),groupeq(drop_while(eqx)l'))letrec_uniqeqprevl()=matchprev,l()with|_,Nil->Nil|None,Cons(x,l')->Cons(x,_uniqeq(Somex)l')|Somey,Cons(x,l')->ifeqxythen_uniqeqprevl'()elseCons(x,_uniqeq(Somex)l')letuniqeql=_uniqeqNonelletrecfilter_mapfl()=matchl()with|Nil->Nil|Cons(x,l')->(matchfxwith|None->filter_mapfl'()|Somey->Cons(y,filter_mapfl'))letflattenl=flat_map(funx->x)lletconcat=flattenletrangeij=letrecauxij()=ifi=jthenCons(i,nil)elseifi<jthenCons(i,aux(i+1)j)elseCons(i,aux(i-1)j)inauxijlet(--)=rangelet(--^)ij=ifi=jthenemptyelseifi<jthenrangei(j-1)elserangei(j+1)letrecfold2faccl1l2=matchl1(),l2()with|Nil,_|_,Nil->acc|Cons(x1,l1'),Cons(x2,l2')->fold2f(faccx1x2)l1'l2'letfold_left2=fold2letrecmap2fl1l2()=matchl1(),l2()with|Nil,_|_,Nil->Nil|Cons(x1,l1'),Cons(x2,l2')->Cons(fx1x2,map2fl1'l2')letreciter2fl1l2=matchl1(),l2()with|Nil,_|_,Nil->()|Cons(x1,l1'),Cons(x2,l2')->fx1x2;iter2fl1'l2'letrecfor_all2fl1l2=matchl1(),l2()with|Nil,_|_,Nil->true|Cons(x1,l1'),Cons(x2,l2')->fx1x2&&for_all2fl1'l2'letrecexists2fl1l2=matchl1(),l2()with|Nil,_|_,Nil->false|Cons(x1,l1'),Cons(x2,l2')->fx1x2||exists2fl1'l2'letrecmergecmpl1l2()=matchl1(),l2()with|Nil,tl2->tl2|tl1,Nil->tl1|Cons(x1,l1'),Cons(x2,l2')->ifcmpx1x2<0thenCons(x1,mergecmpl1'l2)elseCons(x2,mergecmpl1l2')letsorted_merge=mergeletreczipab()=matcha(),b()with|Nil,_|_,Nil->Nil|Cons(x,a'),Cons(y,b')->Cons((x,y),zipa'b')letunzipl=letrecfirstl()=matchl()with|Nil->Nil|Cons((x,_),tl)->Cons(x,firsttl)andsecondl()=matchl()with|Nil->Nil|Cons((_,y),tl)->Cons(y,secondtl)infirstl,secondlletsplit=unzipletzip_iseq=letrecloopiseq()=matchseq()with|Nil->Nil|Cons(x,tl)->Cons((i,x),loop(i+1)tl)inloop0seq(** {2 Implementations} *)letreturnx()=Cons(x,nil)letpure=returnlet(>>=)xsf=flat_mapfxslet(>|=)xsf=mapfxslet(<*>)fsxs=product_with(funfx->fx)fsxs(** {2 Conversions} *)letrec_to_rev_listaccl=matchl()with|Nil->acc|Cons(x,l')->_to_rev_list(x::acc)l'letto_rev_listl=_to_rev_list[]lletto_listl=letrecdirecti(l:'at)=matchl()with|Nil->[]|_wheni=0->List.rev(_to_rev_list[]l)|Cons(x,f)->x::direct(i-1)findirect200lletof_listl=letrecauxl()=matchlwith|[]->Nil|x::l'->Cons(x,auxl')inauxlletof_arraya=letrecauxai()=ifi=Array.lengthathenNilelseCons(a.(i),auxa(i+1))inauxa0letof_strings=letrecauxsi()=ifi=String.lengthsthenNilelseCons(String.getsi,auxs(i+1))inauxs0letto_arrayl=(* We contruct the length and list of seq elements (in reverse) in one pass *)letlen=ref0inletls=fold_left(funaccx->incrlen;x::acc)[]lin(* The length is used to initialize the array, and then to derive the index for
each item, working back from the last. This lets us only traverse the list
twice, instead of having to reverse it. *)matchlswith|[]->[||]|init::rest->leta=Array.make!leninitin(* Subtract 1 for len->index conversion and 1 for the removed [init] *)letidx=!len-2inignore(List.fold_left(funix->a.(i)<-x;i-1)idxrest:int);aletrecto_iterresk=matchres()with|Nil->()|Cons(s,f)->ks;to_iterfkletto_genl=letl=reflinfun()->match!l()with|Nil->None|Cons(x,l')->l:=l';Somextype'aof_gen_state=|Of_gen_thunkof'agen|Of_gen_savedof'anodeletof_geng=letrecconsumer()=match!rwith|Of_gen_savedcons->cons|Of_gen_thunkg->(matchg()with|None->r:=Of_gen_savedNil;Nil|Somex->lettl=consume(ref(Of_gen_thunkg))inletl=Cons(x,tl)inr:=Of_gen_savedl;l)inconsume(ref(Of_gen_thunkg))letsort~cmpl=letl=to_listlinof_list(List.sortcmpl)letsort_uniq~cmpl=letl=to_listlinuniq(funxy->cmpxy=0)(of_list(List.sortcmpl))type'amemoize=|MemoThunk|MemoSaveof'anodeletrecmemoizef=letr=refMemoThunkinfun()->match!rwith|MemoSavel->l|MemoThunk->letl=matchf()with|Nil->Nil|Cons(x,tail)->Cons(x,memoizetail)inr:=MemoSavel;l(** {2 Fair Combinations} *)letrecinterleaveab()=matcha()with|Nil->b()|Cons(x,tail)->Cons(x,interleavebtail)letrecfair_flat_mapfa()=matcha()with|Nil->Nil|Cons(x,tail)->lety=fxininterleavey(fair_flat_mapftail)()letrecfair_appfa()=matchf()with|Nil->Nil|Cons(f1,fs)->interleave(mapf1a)(fair_appfsa)()let(>>-)af=fair_flat_mapfalet(<.>)fa=fair_appfa(** {2 Infix} *)moduleInfix=structlet(>>=)=(>>=)let(>|=)=(>|=)let(<*>)=(<*>)let(>>-)=(>>-)let(<.>)=(<.>)let(--)=(--)let(--^)=(--^)end(** {2 Monadic Operations} *)moduletypeMONAD=sigtype'atvalreturn:'a->'atval(>>=):'at->('a->'bt)->'btendmoduleTraverse(M:MONAD)=structopenMletmap_mfl=letrecauxaccl=matchl()with|Nil->return(of_list(List.revacc))|Cons(x,l')->fx>>=funx'->aux(x'::acc)l'inaux[]lletsequence_ml=map_m(funx->x)lletrecfold_mfaccl=matchl()with|Nil->returnacc|Cons(x,l')->faccx>>=funacc'->fold_mfacc'l'end(** {2 IO} *)letpp?(pp_start=fun_()->())?(pp_stop=fun_()->())?(pp_sep=funout()->Format.fprintfout",@ ")pp_itemfmtl=pp_startfmt();letrecppfmtl=matchl()with|Nil->()|Cons(x,l')->pp_sepfmt();Format.pp_print_cutfmt();pp_itemfmtx;ppfmtl'in(matchl()with|Nil->()|Cons(x,l')->pp_itemfmtx;ppfmtl');pp_stopfmt()