12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652(* backport new functions from stdlib here *)[@@@ocaml.warning"-32"]letreccompare_lengthsl1l2=matchl1,l2with|[],[]->0|[],_::_->-1|_::_,[]->1|_::tail1,_::tail2->compare_lengthstail1tail2letreccompare_length_withln=matchl,nwith|_whenn<0->1|[],0->0|[],_->-1|_::tail,_->compare_length_withtail(n-1)letrecassoc_optx=function|[]->None|(y,v)::_whenStdlib.(=)xy->Somev|_::tail->assoc_optxtailletrecassq_optx=function|[]->None|(y,v)::_whenStdlib.(==)xy->Somev|_::tail->assq_optxtail[@@@ocaml.warning"+32"](* end of backport *)includeListletempty=[]letis_empty=function|[]->true|_::_->falseletmguardc=ifcthen[()]else[](** max depth for direct recursion *)letdirect_depth_default_=1000[@@@iflt4.14]lettail_mapfl=(* Unwind the list of tuples, reconstructing the full list front-to-back.
@param tail_acc a suffix of the final list; we append tuples' content
at the front of it *)letrecrebuildtail_acc=function|[]->tail_acc|(y0,y1,y2,y3,y4,y5,y6,y7,y8)::bs->rebuild(y0::y1::y2::y3::y4::y5::y6::y7::y8::tail_acc)bsin(* Create a compressed reverse-list representation using tuples
@param tuple_acc a reverse list of chunks mapped with [f] *)letrecdivetuple_acc=function|x0::x1::x2::x3::x4::x5::x6::x7::x8::xs->lety0=fx0inlety1=fx1inlety2=fx2inlety3=fx3inlety4=fx4inlety5=fx5inlety6=fx6inlety7=fx7inlety8=fx8indive((y0,y1,y2,y3,y4,y5,y6,y7,y8)::tuple_acc)xs|xs->(* Reverse direction, finishing off with a direct map *)lettail=List.mapfxsinrebuildtailtuple_accindive[]lletmapfl=letrecdirectfil=matchlwith|[]->[]|[x]->[fx]|[x1;x2]->lety1=fx1in[y1;fx2]|[x1;x2;x3]->lety1=fx1inlety2=fx2in[y1;y2;fx3]|_wheni=0->tail_mapfl|x1::x2::x3::x4::l'->lety1=fx1inlety2=fx2inlety3=fx3inlety4=fx4iny1::y2::y3::y4::directf(i-1)l'indirectfdirect_depth_default_lletappendl1l2=let[@inline]safel1l2=List.rev_append(List.revl1)l2inletrecdirectil1l2=matchl1with|[]->l2|[x]->x::l2|_wheni=0->safel1l2|x::y::tl1->x::y::direct(i-1)tl1l2indirect1000l1l2[@@@eliflt5.1]let[@tail_mod_cons]recmapfl=matchlwith|[]->[]|x::tl->letx=fxinx::mapftllet[@tail_mod_cons]recappendl1l2=matchl1with|[]->l2|x::tl1->x::appendtl1l2[@@@else_](* TRMC functions on >= 5.1, no need to bring our own *)[@@@endif](* Wrapper around [append] to optimize for the case of short [l1],
and for the case of [l2 = []] (saves the whole copy of [l1]!) *)let[@inline]appendl1l2=matchl1,l2with|[],_->l2|_,[]->l1|[x],_->x::l2|x::y::tl1,_->x::y::appendtl1l2let(@)=appendlet[@inline]cons'lx=x::lletcons_maybeol=matchowith|Somex->x::l|None->lletcons_whenbxl=ifbthenx::lelsel[@@@iflt4.14]letdirect_depth_filter_=10_000letfilterpl=letrecdirectipl=matchlwith|[]->[]|_wheni=0->safepl[]|x::l'whennot(px)->directipl'|x::l'->x::direct(i-1)pl'andsafeplacc=matchlwith|[]->List.revacc|x::l'whennot(px)->safepl'acc|x::l'->safepl'(x::acc)indirectdirect_depth_filter_pl[@@@eliflt5.1]let[@tail_mod_cons]recfilterfl=matchlwith|[]->[]|x::tl->letkeep=fxinifkeepthenx::filterftlelsefilterftl[@@@else_](* stdlib's filter uses TRMC after 5.1 *)[@@@endif]letfold_rightflacc=letrecdirectiflacc=matchlwith|[]->acc|_wheni=0->safef(List.revl)acc|x::l'->letacc=direct(i-1)fl'accinfxaccandsafeflacc=matchlwith|[]->acc|x::l'->letacc=fxaccinsafefl'accindirectdirect_depth_default_flaccletrecfold_whilefacc=function|[]->acc|e::l->letacc,cont=faccein(matchcontwith|`Stop->acc|`Continue->fold_whilefaccl)letfold_mapfaccl=letrecauxfaccmap_accl=matchlwith|[]->acc,List.revmap_acc|x::l'->letacc,y=faccxinauxfacc(y::map_acc)l'inauxfacc[]lletfold_map_ifaccl=letrecauxfaccimap_accl=matchlwith|[]->acc,List.revmap_acc|x::l'->letacc,y=faccixinauxfacc(i+1)(y::map_acc)l'inauxfacc0[]lletfold_on_map~f~reduceaccl=letrecauxaccl=matchlwith|[]->acc|x::l'->letacc=reduceacc(fx)inauxaccl'inauxacclletscan_leftfaccl=letrecauxfaccl_accl=matchlwith|[]->List.revl_acc|x::tail->letacc=faccxinletl_acc=acc::l_accinauxfaccl_acctailinauxfacc[acc]lletreducef=function|[]->None|x::l->Some(fold_leftfxl)letreduce_exnf=function|[]->raise(Invalid_argument"CCList.reduce_exn")|x::l->fold_leftfxlletfold_map2faccl1l2=letrecauxfaccmap_accl1l2=matchl1,l2with|[],[]->acc,List.revmap_acc|[],_|_,[]->invalid_arg"fold_map2"|x1::l1',x2::l2'->letacc,y=faccx1x2inauxfacc(y::map_acc)l1'l2'inauxfacc[]l1l2letfold_filter_mapfaccl=letrecauxfaccmap_accl=matchlwith|[]->acc,List.revmap_acc|x::l'->letacc,y=faccxinauxfacc(cons_maybeymap_acc)l'inauxfacc[]lletfold_filter_map_ifaccl=letrecauxfaccimap_accl=matchlwith|[]->acc,List.revmap_acc|x::l'->letacc,y=faccixinauxfacc(i+1)(cons_maybeymap_acc)l'inauxfacc0[]lletfold_flat_mapfaccl=letrecauxfaccmap_accl=matchlwith|[]->acc,List.revmap_acc|x::l'->letacc,y=faccxinauxfacc(List.rev_appendymap_acc)l'inauxfacc[]lletfold_flat_map_ifaccl=letrecauxfaccimap_accl=matchlwith|[]->acc,List.revmap_acc|x::l'->letacc,y=faccixinauxfacc(i+1)(List.rev_appendymap_acc)l'inauxfacc0[]l[@@@iflt4.14](* keep this because it's tailrec for < 5.1 *)letinitlenf=letrecindirect_iacc=ifi=lenthenList.revaccelse(letx=fiinindirect_(i+1)(x::acc))inletrecdirect_i=ifi=lenthen[]elseifi<direct_depth_default_then(letx=fiinx::direct_(i+1))elseindirect_i[]iniflen<0theninvalid_arg"init"elseiflen=0then[]elsedirect_0letrecunfold_kontfseedk=matchfseedwith|None->k[]|Some(v,next)->letk'tl=k(v::tl)inunfold_kontfnextk'let[@inline]unfoldfseed=letrecdirectifseed=ifi=0thenunfold_kontfseed(funx->x)else(matchfseedwith|None->[]|Some(v,next)->v::direct(i-1)fnext)indirect100fseed[@@@eliflt5.1]letinitnf=let[@tail_mod_cons]recinit_inf=ifi=nthen[]else(letx=fiinx::init_(i+1)nf)ininit_0nflet[@tail_mod_cons]recunfoldfseed=matchfseedwith|None->[]|Some(v,next)->v::unfoldfnext[@@@else_]let[@tail_mod_cons]recunfoldfseed=matchfseedwith|None->[]|Some(v,next)->v::unfoldfnext[@@@endif]letreccomparefl1l2=matchl1,l2with|[],[]->0|_,[]->1|[],_->-1|x1::l1',x2::l2'->letc=fx1x2inifc<>0thencelsecomparefl1'l2'letrecequalfl1l2=matchl1,l2with|[],[]->true|[],_|_,[]->false|x1::l1',x2::l2'->fx1x2&&equalfl1'l2'[@@@iflt5.1]letrecflat_map_kontflkont=matchlwith|[]->kont[]|[x]->letx=fxinkontx|x::l'->letx=fxinletkont'tail=kont(appendxtail)inflat_map_kontfl'kont'let[@inline]flat_mapfl=matchlwith|[]->[]|[x]->fx|_::_->flat_map_kontflFun.id[@@@else_]letflat_map=concat_map[@@@endif]letflat_map_ifl=letrecauxfilkont=matchlwith|[]->kont[]|x::l'->lety=fixinletkont'tail=matchywith|[]->konttail|[x]->kont(x::tail)|[x;y]->kont(x::y::tail)|l->kont(appendltail)inauxf(i+1)l'kont'inauxf0l(funl->l)letflattenl=fold_rightappendl[]letcountfl=fold_left(funnx->iffxthensuccnelsen)0lletcount_true_falsepl=fold_left(fun(ok,ko)x->ifpxthenok+1,koelseok,ko+1)(0,0)llet[@inline]productfl1l2=flat_map(funx->map(funy->fxy)l2)l1letfold_productfaccl1l2=List.fold_left(funaccx1->List.fold_left(funaccx2->faccx1x2)accl2)accl1letdiagonall=letrecgenaccl=matchlwith|[]->acc|x::l'->letacc=List.fold_left(funaccy->(x,y)::acc)accl'ingenaccl'ingen[]lletpartition_map_eitherfl=letreciterfl1l2l=matchlwith|[]->List.revl1,List.revl2|x::tl->(matchfxwith|CCEither.Lefty->iterf(y::l1)l2tl|CCEither.Righty->iterfl1(y::l2)tl)initerf[][]lletpartition_filter_mapfl=letreciterfl1l2l=matchlwith|[]->List.revl1,List.revl2|x::tl->(matchfxwith|`Lefty->iterf(y::l1)l2tl|`Righty->iterfl1(y::l2)tl|`Drop->iterfl1l2tl)initerf[][]lletpartition_map=partition_filter_map[@@@iflt4.14]letcombinel1l2=letrecdirectil1l2=matchl1,l2with|[],[]->[]|_wheni=0->safel1l2[]|x1::l1',x2::l2'->(x1,x2)::direct(i-1)l1'l2'|_,_->invalid_arg"CCList.combine"andsafel1l2acc=matchl1,l2with|[],[]->List.revacc|x1::l1',x2::l2'->safel1'l2'@@((x1,x2)::acc)|_,_->invalid_arg"CCList.combine"indirectdirect_depth_default_l1l2[@@@else_]let[@tail_mod_cons]reccombinel1l2=matchl1,l2with|[],[]->[]|x1::l1',x2::l2'->(x1,x2)::combinel1'l2'|_,_->invalid_arg"CCList.combine"[@@@endif]letcombine_genl1l2=letl1=refl1inletl2=refl2infun()->match!l1,!l2with|[],_|_,[]->None|x1::tail1,x2::tail2->l1:=tail1;l2:=tail2;Some(x1,x2)[@@@iflt4.14]letcombine_shortestl1l2=letrecdirectil1l2=matchl1,l2with|_,[]|[],_->[]|_wheni=0->safel1l2[]|x1::l1',x2::l2'->(x1,x2)::direct(i-1)l1'l2'andsafel1l2acc=matchl1,l2with|[],_|_,[]->List.revacc|x1::l1',x2::l2'->letacc=(x1,x2)::accinsafel1'l2'accindirectdirect_depth_default_l1l2[@@@else_]let[@tail_mod_cons]reccombine_shortestl1l2=matchl1,l2with|_,[]|[],_->[]|x1::l1',x2::l2'->(x1,x2)::combine_shortestl1'l2'[@@@endif]letsplitl=letrecdirectil=matchlwith|[]->[],[]|[(x1,y1)]->[x1],[y1]|[(x1,y1);(x2,y2)]->[x1;x2],[y1;y2]|[(x1,y1);(x2,y2);(x3,y3)]->[x1;x2;x3],[y1;y2;y3]|[(x1,y1);(x2,y2);(x3,y3);(x4,y4)]->[x1;x2;x3;x4],[y1;y2;y3;y4]|_wheni=0->split_slow[][]l|(x1,y1)::(x2,y2)::(x3,y3)::(x4,y4)::(x5,y5)::l'->letrx,ry=direct(i-1)l'inx1::x2::x3::x4::x5::rx,y1::y2::y3::y4::y5::ryandsplit_slowacc1acc2l=matchlwith|[]->List.revacc1,List.revacc2|(x1,x2)::tail->letacc1=x1::acc1andacc2=x2::acc2insplit_slowacc1acc2tailindirectdirect_depth_default_lletreturnx=[x]letpure=returnlet(<*>)funsl=product(funfx->fx)funslletcartesian_productl=(* [left]: elements picked so far
[right]: sets to pick elements from
[acc]: accumulator for the result, to pass to continuation
[k]: continuation *)letrecprod_recleftrightkacc=matchrightwith|[]->kacc(List.revleft)|l1::tail->List.fold_left(funaccx->prod_rec(x::left)tailkacc)accl1inprod_rec[]l(funaccl'->l'::acc)[](* cartesian product of lists of lists *)letmap_product_lfl=letl=List.mapflincartesian_productlletrecsorted_mem~cmpxl=matchlwith|[]->false|y::tail->(matchcmpxywith|0->true|nwhenn<0->false|_->(sorted_mem[@tailcall])~cmpxtail)letsorted_merge~cmpl1l2=letrecrecursecmpaccl1l2=matchl1,l2with|[],_->List.rev_appendaccl2|_,[]->List.rev_appendaccl1|x1::l1',x2::l2'->letc=cmpx1x2inifc<0thenrecursecmp(x1::acc)l1'l2elseifc>0thenrecursecmp(x2::acc)l1l2'elserecursecmp(x1::x2::acc)l1'l2'inrecursecmp[]l1l2letsorted_diff~cmpl1l2=letrecrecursecmpaccl1l2=matchl1,l2with|[],_->List.revacc|_,[]->List.rev_appendaccl1|x1::l1',x2::l2'->letc=cmpx1x2inifc<0thenrecursecmp(x1::acc)l1'l2elseifc>0thenrecursecmpaccl1l2'elserecursecmpaccl1'l2'inrecursecmp[]l1l2letsort_uniq~cmpl=List.sort_uniqcmplletis_sorted~cmpl=letrecauxcmp=function|[]|[_]->true|x::(y::_astail)->cmpxy<=0&&auxcmptailinauxcmplletsorted_insert~cmp?(uniq=false)xl=letrecauxcmpuniqxleftl=matchlwith|[]->List.rev_appendleft[x]|y::tail->(matchcmpxywith|0->letl'=ifuniqthenlelsex::linList.rev_appendleftl'|nwhenn<0->List.rev_appendleft(x::l)|_->auxcmpuniqx(y::left)tail)inauxcmpuniqx[]lletsorted_remove~cmp?(all=false)xl=letrecauxcmpallxleftl=matchlwith|[]->List.revleft|y::tail->(matchcmpxywith|0->ifallthenauxcmpallxlefttailelseList.rev_appendlefttail|nwhenn<0->List.rev_appendleftl|_->auxcmpallx(y::left)tail)inauxcmpallx[]lletuniq_succ~eql=letrecfaccl=matchlwith|[]->List.revacc|[x]->List.rev(x::acc)|x::(y::_astail)wheneqxy->facctail|x::tail->f(x::acc)tailinf[]lletgroup_succ~eql=letrecf~eqacccurl=matchcur,lwith|[],[]->List.revacc|_::_,[]->List.rev(List.revcur::acc)|[],x::tl->f~eqacc[x]tl|y::_,x::tlwheneqxy->f~eqacc(x::cur)tl|_,x::tl->f~eq(List.revcur::acc)[x]tlinf~eq[][]lletsorted_merge_uniq~cmpl1l2=letpush~cmpaccx=matchaccwith|[]->[x]|y::_whencmpxy>0->x::acc|_->acc(* duplicate, do not yield *)inletrecrecurse~cmpaccl1l2=matchl1,l2with|[],l|l,[]->letacc=List.fold_left(push~cmp)acclinList.revacc|x1::l1',x2::l2'->letc=cmpx1x2inifc<0thenrecurse~cmp(push~cmpaccx1)l1'l2elseifc>0thenrecurse~cmp(push~cmpaccx2)l1l2'elserecurse~cmpaccl1l2'(* drop one of the [x] *)inrecurse~cmp[]l1l2letsorted_diff_uniq~cmpl1l2=letpush~cmpaccx=matchaccwith|[]->[x]|y::_whencmpxy>0->x::acc|_->acc(* duplicate, do not yield *)inletrecrecurse~cmpaccl1l2=matchl1,l2with|[],_->List.revacc|l,[]->letacc=List.fold_left(push~cmp)acclinList.revacc|x1::l1',x2::l2'->letc=cmpx1x2inifc<0thenrecurse~cmp(push~cmpaccx1)l1'l2elseifc>0thenrecurse~cmpaccl1l2'elserecurse~cmpaccl1'l2'inrecurse~cmp[]l1l2[@@@iflt4.14]lettakenl=letrecdirectinl=matchlwith|[]->[]|_wheni=0->safen[]l|x::l'->ifn>0thenx::direct(i-1)(n-1)l'else[]andsafenaccl=matchlwith|[]->List.revacc|_whenn=0->List.revacc|x::l'->safe(n-1)(x::acc)l'indirectdirect_depth_default_nl[@@@else_]let[@tail_mod_cons]rectakenl=matchlwith|[]->[]|x::l'->ifn>0thenx::take(n-1)l'else[][@@@endif]letrecdropnl=matchlwith|[]->[]|_whenn=0->l|_::l'->drop(n-1)l'lethd_tl=function|[]->failwith"hd_tl"|x::l->x,llettake_dropnl=takenl,dropnlletsublists_of_len?(last=fun_->None)?offsetnl=ifn<1theninvalid_arg"sublists_of_len: n must be > 0";letoffset=matchoffsetwith|None->n|Someowheno<1->invalid_arg"sublists_of_len: offset must be > 0"|Someo->oin(* add sub-lists of [l] to [acc] *)letrecauxaccl=letgroup=takenlinifis_emptygroupthenacc(* this was the last group, we are done *)elseifList.lengthgroup<n(* last group, with missing elements *)then(matchlastgroupwith|None->acc|Somegroup'->group'::acc)else(letl'=dropoffsetlinaux(group::acc)l'(* continue *))inList.rev(aux[]l)letchunksnl=sublists_of_len~last:(funx->Somex)nlletinterspersexl=letrecaux_directixl=matchlwith|[]->[]|[_]->l|_wheni=0->aux_tailrec[]xl|y::tail->y::x::aux_direct(i-1)xtailandaux_tailrecaccxl=matchlwith|[]->List.revacc|[y]->List.rev(y::acc)|y::tail->aux_tailrec(x::y::acc)xtailinaux_direct1_000xlletinterleavel1l2:_list=letrecauxaccl1l2=matchl1,l2with|[],[]->List.revacc|[],_->List.rev(List.rev_appendl2acc)|_,[]->List.rev(List.rev_appendl1acc)|x1::tl1,x2::tl2->aux(x2::x1::acc)tl1tl2inaux[]l1l2[@@@iflt4.14]lettake_whilepl=letrecdirectipl=matchlwith|[]->[]|_wheni=0->safep[]l|x::l'->ifpxthenx::direct(i-1)pl'else[]andsafepaccl=matchlwith|[]->List.revacc|x::l'->ifpxthensafep(x::acc)l'elseList.revaccindirectdirect_depth_default_pl[@@@else_]let[@tail_mod_cons]rectake_whilepl=matchlwith|[]->[]|x::l'->ifpxthenx::take_whilepl'else[][@@@endif]letrecdrop_whilepl=matchlwith|[]->[]|x::l'->ifpxthendrop_whilepl'elsellettake_drop_whilepl=letrecdirectipl=matchlwith|[]->[],[]|_wheni=0->safep[]l|x::tail->ifpxthen(letl1,l2=direct(i-1)ptailinx::l1,l2)else[],landsafepaccl=matchlwith|[]->List.revacc,[]|x::tail->ifpxthensafep(x::acc)tailelseList.revacc,lindirectdirect_depth_default_plletlastnl=letlen=List.lengthliniflen<nthenlelsedrop(len-n)llethead_opt=function|[]->None|x::_->Somexlettail_opt=function|[]->None|_::tail->Sometailletreclast_opt=function|[]->None|[x]->Somex|_::tail->last_opttailletfind_pred=find_optletfind_pred_exnpl=matchfind_predplwith|None->raiseNot_found|Somex->xletfind_mapifl=letrecauxfi=function|[]->None|x::l'->(matchfixwith|Some_asres->res|None->auxf(i+1)l')inauxf0lletfind_mapfl=find_mapi(fun_->f)lletfind_idxpl=find_mapi(funix->ifpxthenSome(i,x)elseNone)lletremove~eqxl=letrecremove'eqxaccl=matchlwith|[]->List.revacc|y::tailwheneqxy->remove'eqxacctail|y::tail->remove'eqx(y::acc)tailinremove'eqx[]lletfilter_mapfl=letrecrecurseaccl=matchlwith|[]->List.revacc|x::l'->letacc'=matchfxwith|None->acc|Somey->y::accinrecurseacc'l'inrecurse[]lletkeep_somel=filter_map(funx->x)lletkeep_okl=filter_map(function|Okx->Somex|Error_->None)lletall_somel=trySome(map(function|Somex->x|None->raiseExit)l)withExit->Noneletall_okl=leterr=refNoneintryOk(map(function|Okx->x|Errore->err:=Somee;raiseExit)l)withExit->(match!errwith|None->assertfalse|Somee->Errore)letsplit_resultresults=results|>partition_filter_map(funx->matchxwith|Oko->`Lefto|Errore->`Righte)letgroup_by(typek)?(hash=Hashtbl.hash)?(eq=Stdlib.(=))l=letmoduleTbl=Hashtbl.Make(structtypet=kletequal=eqlethash=hashend)in(* compute group table *)lettbl=Tbl.create32inList.iter(funx->letl=tryTbl.findtblxwithNot_found->[]inTbl.replacetblx(x::l))l;Tbl.fold(fun_xacc->x::acc)tbl[]letjoin~join_rows1s2:_t=flat_map(funa->filter_map(join_rowa)s2)s1letjoin_by(typea)?(eq=Stdlib.(=))?(hash=Hashtbl.hash)f1f2~mergec1c2=letmoduleTbl=Hashtbl.Make(structtypet=aletequal=eqlethash=hashend)inlettbl=Tbl.create32inList.iter(funx->letkey=f1xinTbl.addtblkeyx)c1;letres=ref[]inList.iter(funy->letkey=f2yinletxs=Tbl.find_alltblkeyinList.iter(funx->matchmergekeyxywith|None->()|Somez->res:=z::!res)xs)c2;!restype('a,'b)join_all_cell={mutableja_left:'alist;mutableja_right:'blist;}letjoin_all_by(typea)?(eq=Stdlib.(=))?(hash=Hashtbl.hash)f1f2~mergec1c2=letmoduleTbl=Hashtbl.Make(structtypet=aletequal=eqlethash=hashend)inlettbl=Tbl.create32in(* build the map [key -> cell] *)List.iter(funx->letkey=f1xintryletc=Tbl.findtblkeyinc.ja_left<-x::c.ja_leftwithNot_found->Tbl.addtblkey{ja_left=[x];ja_right=[]})c1;List.iter(funy->letkey=f2yintryletc=Tbl.findtblkeyinc.ja_right<-y::c.ja_rightwithNot_found->Tbl.addtblkey{ja_left=[];ja_right=[y]})c2;Tbl.fold(funkeycellres->matchmergekeycell.ja_leftcell.ja_rightwith|None->res|Somez->z::res)tbl[]letgroup_join_by(typea)?(eq=Stdlib.(=))?(hash=Hashtbl.hash)fc1c2=letmoduleTbl=Hashtbl.Make(structtypet=aletequal=eqlethash=hashend)inlettbl=Tbl.create32inList.iter(funx->Tbl.replacetblx[])c1;List.iter(funy->(* project [y] into some element of [c1] *)letkey=fyintryletl=Tbl.findtblkeyinTbl.replacetblkey(y::l)withNot_found->())c2;Tbl.fold(funkvl->(k,v)::l)tbl[]letmem?(eq=Stdlib.(=))xl=letrecsearcheqxl=matchlwith|[]->false|y::l'->eqxy||searcheqxl'insearcheqxlletadd_nodup~eqxl=ifmem~eqxlthenlelsex::lletremove_one~eqxl=letrecremove_one~eqxaccl=matchlwith|[]->assertfalse|y::tlwheneqxy->List.rev_appendacctl|y::tl->remove_one~eqx(y::acc)tlinifmem~eqxlthenremove_one~eqx[]lelselletsubset~eql1l2=List.for_all(funt->mem~eqtl2)l1letuniq~eql=letrecuniqeqaccl=matchlwith|[]->List.revacc|x::xswhenList.exists(eqx)xs->uniqeqaccxs|x::xs->uniqeq(x::acc)xsinuniqeq[]lletunion~eql1l2=letrecunioneqaccl1l2=matchl1with|[]->List.rev_appendaccl2|x::xswhenmem~eqxl2->unioneqaccxsl2|x::xs->unioneq(x::acc)xsl2inunioneq[]l1l2letinter~eql1l2=letrecintereqaccl1l2=matchl1with|[]->List.revacc|x::xswhenmem~eqxl2->intereq(x::acc)xsl2|_::xs->intereqaccxsl2inintereq[]l1l2letmapifl=letr=ref0inmap(funx->lety=f!rxinincrr;y)lletiterifl=letrecauxfil=matchlwith|[]->()|x::l'->fix;auxf(i+1)l'inauxf0lletiteri2fl1l2=letrecauxfil1l2=matchl1,l2with|[],[]->()|[],_|_,[]->invalid_arg"iteri2"|x1::l1',x2::l2'->fix1x2;auxf(i+1)l1'l2'inauxf0l1l2letfoldifaccl=letrecfoldifaccil=matchlwith|[]->acc|x::l'->letacc=faccixinfoldifacc(i+1)l'infoldifacc0lletfoldi2faccl1l2=letrecfoldifaccil1l2=matchl1,l2with|[],[]->acc|[],_|_,[]->invalid_arg"foldi2"|x1::l1',x2::l2'->letacc=faccix1x2infoldifacc(i+1)l1'l2'infoldifacc0l1l2letrecget_at_idx_recil=matchlwith|[]->raiseNot_found|x::_wheni=0->x|_::l'->get_at_idx_rec(i-1)l'letget_at_idx_exnil=leti=ifi<0thenlengthl+ielseiinget_at_idx_recilletget_at_idxil=trySome(get_at_idx_exnil)withNot_found->Noneletset_at_idxixl0=letrecauxlacci=matchlwith|[]->l0|_::l'wheni=0->List.rev_appendacc(x::l')|y::l'->auxl'(y::acc)(i-1)inleti=ifi<0thenlengthl0+ielseiinauxl0[]iletinsert_at_idxixl=letrecauxlaccix=matchlwith|[]->List.rev_appendacc[x]|y::l'wheni=0->List.rev_appendacc(x::y::l')|y::l'->auxl'(y::acc)(i-1)xinleti=ifi<0thenlengthl+ielseiinauxl[]ixletremove_at_idxil0=letrecauxlacci=matchlwith|[]->l0|_::l'wheni=0->List.rev_appendaccl'|y::l'->auxl'(y::acc)(i-1)inleti=ifi<0thenlengthl0+ielseiinauxl0[]iletrange_by~stepij=letrecrangeijacc=ifi=jtheni::accelserangei(j-step)(j::acc)inifstep=0thenraise(Invalid_argument"CCList.range_by")elseififstep>0theni>jelsei<jthen[]elserangei(((j-i)/step*step)+i)[]letrangeij=letrecupijacc=ifi=jtheni::accelseupi(j-1)(j::acc)anddownijacc=ifi=jtheni::accelsedowni(j+1)(j::acc)inifi<=jthenupij[]elsedownij[]letrange'ij=ifi<jthenrangei(j-1)elseifi=jthen[]elserangei(j+1)let(--)=rangelet(--^)=range'letreplicateix=letrecauxacci=ifi=0thenaccelseaux(x::acc)(i-1)inaux[]iletrepeatil=letrecauxacci=ifi=0thenList.revaccelseaux(List.rev_appendlacc)(i-1)inaux[]imoduleAssoc=structtype('a,'b)t=('a*'b)listletrecsearch_exneqlx=matchlwith|[]->raiseNot_found|(y,z)::l'->ifeqxythenzelsesearch_exneql'xletget_exn~eqxl=search_exneqlxletget~eqxl=trySome(search_exneqlx)withNot_found->None(* search for a binding for [x] in [l], and calls [f x (Some v) rest]
or [f x None rest] depending on whether it finds the binding.
[rest] is the list of the other bindings *)letrecsearch_seteqacclx~f=matchlwith|[]->fxNoneacc|(x',y')::l'->ifeqxx'thenfx(Somey')(List.rev_appendaccl')elsesearch_seteq((x',y')::acc)l'x~fletset~eqxyl=search_seteq[]lx~f:(funx_l->(x,y)::l)letmem?(eq=Stdlib.(=))xl=tryignore(search_exneqlx);truewithNot_found->falseletupdate~eqfxl=search_seteq[]lx~f:(funxopt_yrest->matchfopt_ywith|None->rest(* drop *)|Somey'->(x,y')::rest)letremove~eqxl=search_seteq[]lx~f:(fun_opt_yrest->matchopt_ywith|None->l(* keep as is *)|Some_->rest)letkeysl=map(fun(k,_)->k)lletvaluesl=map(fun(_,v)->v)lletmap_valuesfl=map(fun(k,v)->k,fv)lendletassoc=Assoc.get_exnletassoc_opt=Assoc.getletmem_assoc=Assoc.memletremove_assoc=Assoc.remove(** {2 References on Lists} *)moduleRef=structtype'at='alistrefletpushlx=l:=x::!lletpopl=match!lwith|[]->None|x::tail->l:=tail;Somexletpop_exnl=match!lwith|[]->failwith"CCList.Ref.pop_exn"|x::tail->l:=tail;xletcreate()=ref[]letclearl=l:=[]letliftfl=f!lletpush_listrl=r:=List.rev_appendl!rend(** {2 Monadic Operations} *)moduletypeMONAD=sigtype'atvalreturn:'a->'atval(>>=):'at->('a->'bt)->'btendmoduleTraverse(M:MONAD)=structopenMletmap_mfl=letrecauxfaccl=matchlwith|[]->return(List.revacc)|x::tail->fx>>=funx'->auxf(x'::acc)tailinauxf[]lletrecmap_m_parfl=matchlwith|[]->M.return[]|x::tl->letx'=fxinlettl'=map_m_parftlinx'>>=funx'->tl'>>=funtl'->M.return(x'::tl')letsequence_ml=map_m(funx->x)lletrecfold_mfaccl=matchlwith|[]->returnacc|x::l'->faccx>>=funacc'->fold_mfacc'l'end(** {2 Conversions} *)type'aiter=('a->unit)->unittype'agen=unit->'aoptiontype'aprinter=Format.formatter->'a->unittype'arandom_gen=Random.State.t->'aletrandom_lenlengst=initlen(fun_->gst)letrandomgst=letlen=Random.State.intst1_000inrandom_lenlengstletrandom_non_emptygst=letlen=1+Random.State.intst1_000inrandom_lenlengstletrandom_choosel=matchlwith|[]->raiseNot_found|_::_->letlen=List.lengthlinfunst->leti=Random.State.intstleninList.nthliletrandom_sequencelst=map(fung->gst)lletto_string?(start="")?(stop="")?(sep=", ")item_to_stringl=letl=List.mapitem_to_stringlinstart^String.concatsepl^stopletto_iterlk=List.iterklletrecto_seql()=matchlwith|[]->Seq.Nil|x::tl->Seq.Cons(x,to_seqtl)letof_iteri=letl=ref[]ini(funx->l:=x::!l);List.rev!lletof_seq_revl=letrecloopaccs=matchs()with|Seq.Nil->acc|Seq.Cons(x,tl)->loop(x::acc)tlinloop[]l[@@@iflt4.14]letof_seql=letrecdirectiseq=ifi<=0thenList.rev(of_seq_revseq)else(matchseq()with|Seq.Nil->[]|Seq.Cons(x,tl)->x::direct(i-1)tl)indirectdirect_depth_default_l[@@@endif]letto_genl=letl=reflinfun()->match!lwith|[]->None|x::l'->l:=l';Somex[@@@iflt4.14]letof_geng=letrecdirectig=ifi=0thensafe[]gelse(matchg()with|None->[]|Somex->x::direct(i-1)g)andsafeaccg=matchg()with|None->List.revacc|Somex->safe(x::acc)gindirectdirect_depth_default_g[@@@else_]let[@tail_mod_cons]recof_geng=matchg()with|None->[]|Somex->x::of_geng[@@@endif]moduleInfix=structlet[@inline](>|=)lf=mapfllet[@inline](>>=)lf=flat_mapfllet(@)=(@)let(<*>)=(<*>)let(<$>)=maplet(--)=(--)let(--^)=(--^)let(let+)=(>|=)let(let*)=(>>=)let[@inline](and+)l1l2=product(funxy->x,y)l1l2let(and*)=(and+)let(and&)=combine_shortestendincludeInfix(** {2 IO} *)letpp?(pp_start=fun_()->())?(pp_stop=fun_()->())?(pp_sep=funfmt()->Format.fprintffmt",@ ")pp_itemfmtl=letrecprintfmtl=matchlwith|x::(_::_asl)->pp_itemfmtx;pp_sepfmt();printfmtl|[x]->pp_itemfmtx|[]->()inpp_startfmt();printfmtl;pp_stopfmt()