1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255(*
* Copyright (C) 2011 Batteries Included Development Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)type'amonoid={zero:'a;combine:'a->'a->'a;}moduletypeS=sigtype('a,'m)fgtype('wrapped_type,'a,'m)wrapvalempty:('a,'m)fgvalsingleton:'a->('a,'m)fgvalcons:(('a,'m)fg->'a->('a,'m)fg,'a,'m)wrapvalsnoc:(('a,'m)fg->'a->('a,'m)fg,'a,'m)wrapvalfront:(('a,'m)fg->(('a,'m)fg*'a)option,'a,'m)wrapvalfront_exn :(('a,'m)fg->(('a,'m)fg*'a),'a,'m)wrapvalhead:('a,'m)fg->'aoptionvalhead_exn :('a,'m)fg->'avallast:('a,'m)fg-> 'aoptionvallast_exn :('a,'m)fg->'avaltail:(('a,'m)fg->('a,'m)fgoption,'a,'m)wrapvaltail_exn :(('a,'m)fg->('a,'m)fg,'a,'m)wrapvalinit:(('a,'m)fg->('a,'m)fgoption,'a,'m)wrapvalinit_exn :(('a,'m)fg->('a,'m)fg,'a,'m)wrapvalrear:(('a,'m)fg->(('a,'m)fg*'a)option,'a,'m)wrapvalrear_exn :(('a,'m)fg->(('a,'m)fg*'a),'a,'m)wrapvalsize:('a,'m)fg-> intvalis_empty:('a,'m)fg->boolvalfold_left:('acc->'a->'acc)->'acc->('a,'m)fg->'accvalfold_right:('acc-> 'a->'acc)->'acc->('a,'m)fg->'accvaliter:('a->unit)->('a,'m)fg->unitvaliter_right:('a->unit)->('a,'m)fg->unitvalcompare:('a->'a->int)->('a,'m)fg->('a,'m)fg->intval equal:('a->'a->bool)->('a,'m)fg->('a,'m)fg->boolval enum:('a,'m)fg-> 'aBatEnum.tvalbackwards :('a,'m)fg->'aBatEnum.tvalto_list :('a,'m)fg ->'alistvalto_list_backwards:('a,'m)fg->'alistvalof_enum:('aBatEnum.t->('a,'m)fg,'a,'m)wrapvalof_backwards :('aBatEnum.t->('a,'m)fg,'a,'m)wrapvalof_list :('alist-> ('a,'m)fg,'a,'m)wrapvalof_list_backwards :('alist->('a,'m)fg,'a,'m)wrapvalmap:(('a->'b)->('a,'m)fg->('b,'m)fg,'b,'m)wrapvalmap_right :(('a->'b)->('a,'m)fg->('b,'m)fg,'b,'m)wrapvalappend:(('a,'m)fg ->('a,'m)fg->('a,'m)fg,'a,'m)wrapvalreverse :(('a,'m)fg->('a,'m)fg,'a,'m)wrapvalprint:?first:string ->?last:string->?sep:string->('aBatInnerIO.output->'b->unit)->'aBatInnerIO.output->('b,_)fg->unitendexceptionEmptymodule Generic =struct(* All the datatypes in here are the same as the same described in the
* paper in the mli.
* Since there are several variants mentioned:
* - we define 'a digit not as being an 'a list as done initially in the
* paper but (as suggested later) as a sum types that cover sequence of
* length 1, 2, 3 or 4
* I didn't test with lists, but I suspect it would be slower and take
* more memory. On the minus side, the code is rather annoying to write
* with the current digits.
* - there are measure caches not only on nodes, but also on digits.
* It is slightly faster when benchmarking construction/deconstruction
* even with dummy annotations.
* In many places, it looks like functions are defined twice in slightly
* different versions. This is for performance reasons, to avoid higher
* order calls (made everything 30% slower on my tests).
*)type('a,'m)node=|Node2of'm*'a*'a|Node3of'm*'a*'a*'atype('a,'m)digit=|Oneof'm*'a|Twoof'm*'a*'a|Threeof'm*'a*'a*'a|Fourof'm*'a*'a*'a*'atype('a,'m)fg=|Nil(* not called Empty as in the paper to avoid a name
* clash with the exception Empty *)|Singleof'a|Deepof'm*('a,'m)digit*(('a,'m)node,'m)fg*('a,'m)digitletempty =Nilletsingletona=Singlealetis_empty=function|Nil->true|Single_|Deep_->false(*---------------------------------*)(* fold *)(*---------------------------------*)letfold_right_nodefacc=function|Node2(_,a,b)->f(faccb)a|Node3(_,a,b,c)->f(f(faccc)b)aletfold_left_nodefacc=function|Node2(_,a,b)->f(facca)b|Node3(_,a,b,c)->f(f(facca)b)cletfold_right_digitfacc=function|One(_,a)->facca|Two(_,a,b)->f(faccb)a|Three(_,a,b,c)->f(f(faccc)b)a|Four(_,a,b,c,d)->f(f(f(faccd)c)b)aletfold_left_digitfacc=function|One(_,a)->facca|Two(_,a,b)->f(facca)b|Three(_,a,b,c)->f(f(facca)b)c|Four(_,a,b,c,d)->f(f(f(facca)b)c)dletrecfold_right:'acc'a'm.('acc->'a->'acc)->'acc->('a,'m)fg->'acc=funfacc->function|Nil->acc|Singlex->faccx|Deep(_,pr,m,sf)->letacc=fold_right_digitfaccsfinletacc=fold_right(funaccelt->fold_right_nodefacc elt)accminletacc=fold_right_digitfaccprinaccletrecfold_left:'acc'a'm.('acc->'a->'acc)->'acc->('a,'m)fg->'acc=funfacc->function|Nil->acc|Singlex->faccx|Deep(_,pr,m,sf)->letacc=fold_left_digitfaccprinletacc=fold_left(funaccelt->fold_left_nodefaccelt)accminletacc=fold_left_digitfaccsfinacc(*---------------------------------*)(* debug printing *)(*---------------------------------*)letpp_debug_digitpp_measurepp_af=function|One(m,a)->Format.fprintff"@[@[<2>One (@,%a,@ %a@])@]"pp_measurempp_aa|Two(m,a,b)->Format.fprintff"@[@[<2>Two (@,%a,@ %a,@%a@])@]"pp_measurempp_aapp_ab|Three(m,a,b,c)->Format.fprintff"@[@[<2>Three (@,%a,@ %a,@ %a,@ %a@])@]"pp_measurempp_aapp_abpp_ac|Four(m,a,b,c,d)->Format.fprintff"@[@[<2>Four (@,%a,@ %a,@%a,@ %a,@ %a@])@]"pp_measurempp_aapp_abpp_acpp_adletpp_debug_nodepp_measure pp_af=function|Node2(m,a,b)->Format.fprintff"@[@[<2>Node2 (@,%a,@ %a,@ %a@])@]"pp_measurempp_aapp_ab|Node3(m,a,b,c)->Format.fprintff"@[@[<2>Node3 (@,%a,@ %a,@ %a,@ %a@])@]"pp_measurempp_aapp_abpp_actype'aprinter=Format.formatter->'a->unitletrecpp_debug_tree:'a'm.'mprinter->'aprinter->('a,'m)fgprinter=funpp_measurepp_af->function|Nil->Format.fprintff"Nil"|Singlea->Format.fprintff"@[<2>Single@ %a@]"pp_aa|Deep(v,pr,m,sf)->Format.fprintff"@[@[<v2>Deep (@,%a,@ %a,@ %a,@ %a@]@\n)@]"pp_measurev(pp_debug_digitpp_measurepp_a)pr(pp_debug_treepp_measure (pp_debug_nodepp_measurepp_a))m(pp_debug_digitpp_measurepp_a)sfletdummy_printerf_=Format.pp_print_stringf"_"letpp_debug?(pp_measure=dummy_printer)pp_aft=pp_debug_treepp_measurepp_aftletpp_listpp_a f=function|[]->Format.fprintff"[]"|h::t->Format.fprintff"[%a"pp_ah;List.iter(funa->Format.fprintff"; %a"pp_aa)t;Format.fprintff"]"(*---------------------------------*)(* measurement functions *)(*---------------------------------*)type('wrapped_type,'a,'m)wrap=monoid:'mmonoid->measure:('a->'m)->'wrapped_typeletmeasure_node=function|Node2(v,_,_)|Node3(v,_,_,_)->vletmeasure_digit=function|One(v,_)|Two(v,_,_)|Three(v,_,_,_)|Four(v,_,_,_,_)->vletmeasure_t_node~monoid=function|Nil->monoid.zero|Singlex->measure_node x|Deep(v,_,_,_)->vletmeasure_t~monoid~measure=function|Nil->monoid.zero|Singlex->measure x|Deep(v,_,_,_)->vletcheck_measures_digit~monoid~measure~eqcheck=function|One(v,a)->checka&&eq(measurea)v|Two(v,a,b)->checka&&checkb&&eq(monoid.combine(measurea)(measure b))v|Three (v,a,b,c)->checka&&checkb&&checkc&&eq(monoid.combine(monoid.combine(measurea)(measure b))(measurec))v|Four(v,a,b,c,d)->checka&&checkb&&checkc&&checkd&&eq(monoid.combine(monoid.combine(measurea)(measure b))(monoid.combine(measurec)(measure d)))vletcheck_measures_node~monoid~measure~eqcheck=function|Node2(v,a,b)->checka&&checkb&&eq(monoid.combine(measurea)(measure b))v|Node3 (v,a,b,c)->checka&&checkb&&checkc&&eq(monoid.combine(monoid.combine(measurea)(measure b))(measurec))vletreccheck_measures:'a'm.monoid:'mmonoid->measure:('a->'m)->eq:('m->'m->bool)->('a->bool)->('a,'m)fg->bool=fun~monoid~measure~eqcheck->function|Nil->true|Singlea->checka|Deep(v,pr,m,sf)->check_measures_digit~monoid~measure~eqcheckpr&&check_measures_digit ~monoid~measure~eqchecksf&&check_measures ~monoid~measure:measure_node~eq(funa->check_measures_node~monoid~measure~eqchecka)m&&eq(monoid.combine(measure_digitpr)(monoid.combine(measure_t_node~monoidm)(measure_digitsf)))vletcheck_measures~monoid~measure~eqt=check_measures~monoid~measure~eq(fun_->true)t(*---------------------------------*)(* a bunch of smart constructors *)(*---------------------------------*)letnode2~monoid~measureab=Node2(monoid.combine(measurea)(measure b),a,b)letnode2_node~monoidab=Node2(monoid.combine (measure_nodea)(measure_nodeb),a,b)letnode3~monoid~measureabc=Node3(monoid.combine(measurea)(monoid.combine(measureb)(measure c)),a,b,c)letnode3_node ~monoidabc=Node3(monoid.combine(measure_nodea)(monoid.combine(measure_nodeb)(measure_nodec)),a,b,c)letdeep~monoidprmsf=letv=measure_digit prinletv=monoid.combinev(measure_t_node~monoidm)inletv=monoid.combinev(measure_digitsf)inDeep(v,pr,m,sf)letone_nodea=One (measure_nodea,a)letone~measurea=One(measurea,a)lettwo_node~monoidab=Two(monoid.combine(measure_nodea)(measure_nodeb),a,b)lettwo~monoid~measureab=Two(monoid.combine(measurea)(measure b),a,b)letthree_node~monoidabc=Three(monoid.combine(monoid.combine(measure_nodea)(measure_nodeb))(measure_nodec),a,b,c)letthree~monoid~measureabc=Three(monoid.combine(monoid.combine(measurea)(measure b))(measurec),a,b,c)letfour_node ~monoidabcd=Four(monoid.combine(monoid.combine(measure_nodea)(measure_nodeb))(monoid.combine(measure_nodec)(measure_noded)),a,b,c,d)letfour~monoid~measureabcd=Four (monoid.combine(monoid.combine(measurea)(measure b))(monoid.combine(measurec)(measure d)),a,b,c,d)(*---------------------------------*)(* cons / snoc *)(*---------------------------------*)letcons_digit_node~monoiddx=matchdwith|One(v,a)->Two(monoid.combine(measure_nodex)v,x,a)|Two(v,a,b)->Three(monoid.combine(measure_nodex)v,x,a,b)|Three(v,a,b,c)->Four(monoid.combine(measure_nodex)v,x,a,b,c)|Four_->assertfalseletcons_digit~monoid~measuredx=matchdwith|One(v,a)->Two(monoid.combine(measurex)v,x,a)|Two(v,a,b)->Three(monoid.combine(measurex)v,x,a,b)|Three(v,a,b,c)->Four(monoid.combine(measurex)v,x,a,b,c)|Four_->assertfalseletsnoc_digit_node~monoiddx=matchdwith|One(v,a)->Two(monoid.combinev(measure_nodex),a,x)|Two(v,a,b)->Three(monoid.combinev(measure_nodex),a,b,x)|Three(v,a,b,c)->Four(monoid.combinev(measure_nodex),a,b,c,x)|Four_->assertfalseletsnoc_digit~monoid~measuredx=matchdwith|One(v,a)->Two(monoid.combinev(measurex),a,x)|Two(v,a,b)->Three(monoid.combinev(measurex),a,b,x)|Three(v,a,b,c)->Four(monoid.combinev(measurex),a,b,c,x)|Four_->assertfalseletreccons_aux:'a'm.monoid:'mmonoid->(('a,'m)node,'m)fg->('a,'m)node-> (('a,'m)node,'m)fg=fun~monoidta->matchtwith|Nil->Singlea|Singleb->deep~monoid(one_nodea)Nil(one_nodeb)|Deep(_,Four(_,b,c,d,e),m,sf)->deep~monoid(two_node~monoidab)(cons_aux ~monoidm(node3_node~monoidcde))sf|Deep(v,pr,m,sf)->Deep(monoid.combine (measure_nodea)v,cons_digit_node~monoidpra,m,sf)letcons~monoid~measureta=matchtwith|Nil->Singlea|Singleb->deep~monoid(one~measurea)Nil(one~measureb)|Deep(_,Four(_,b,c,d,e),m,sf)->deep~monoid(two~monoid~measureab)(cons_aux~monoidm(node3~monoid~measurecde))sf|Deep(v,pr,m,sf)->Deep(monoid.combine(measurea)v,cons_digit ~monoid~measurepra,m,sf)letrecsnoc_aux :'a'm.monoid:'mmonoid->(('a,'m)node,'m)fg->('a,'m)node-> (('a,'m)node,'m)fg=fun~monoidta->matchtwith|Nil->Singlea|Singleb->deep~monoid(one_nodeb)Nil(one_nodea)|Deep(_,pr,m,Four(_,b,c,d,e))->deep~monoidpr(snoc_aux~monoidm(node3_node ~monoidbcd))(two_node~monoidea)|Deep(v,pr,m,sf)->Deep(monoid.combine v(measure_nodea),pr,m,snoc_digit_node~monoidsfa)letsnoc~monoid~measureta=matchtwith|Nil->Singlea|Singleb->deep~monoid(one~measureb)Nil(one~measurea)|Deep(_,pr,m,Four(_,b,c,d,e))->deep~monoidpr(snoc_aux~monoidm(node3~monoid~measurebcd))(two~measure~monoidea)|Deep(v,pr,m,sf)->Deep(monoid.combinev(measurea),pr,m,snoc_digit~monoid~measuresfa)(*---------------------------------*)(* various conversions *)(*---------------------------------*)letto_tree_digit_node~monoidd=matchdwith|One(_,a)->Singlea|Two(v,a,b)->Deep(v,one_nodea,Nil,one_nodeb)|Three(v,a,b,c)->Deep(v,two_node~monoidab,Nil,one_nodec)|Four(v,a,b,c,d)->Deep(v,three_node~monoidabc,Nil,one_noded)letto_tree_digit~monoid~measured=matchdwith|One(_,a)->Singlea|Two(v,a,b)->Deep(v,one~measurea,Nil,one~measureb)|Three(v,a,b,c)->Deep(v,two~monoid~measureab,Nil,one~measurec)|Four(v,a,b,c,d)->Deep(v,three~monoid~measureabc,Nil,one~measured)letto_tree_list~monoid~measure=function|[]->Nil|[a]->Singlea|[a;b]->deep~monoid(one~measurea)Nil(one~measureb)|[a;b;c]->deep~monoid(two~monoid~measureab)Nil(one~measurec)|[a;b;c;d]->deep ~monoid(three~monoid~measureabc)Nil(one~measured)|_->assertfalseletto_digit_node=function|Node2(v,a,b)->Two(v,a,b)|Node3(v,a,b,c)->Three(v,a,b,c)letto_digit_list~monoid~measure=function|[a]->one ~measurea|[a;b]->two~monoid~measureab|[a;b;c]->three~monoid~measureabc|[a;b;c;d]->four~monoid~measureabcd|_-> assertfalseletto_digit_list_node~monoid=function|[a]->one_node a|[a;b]->two_node~monoidab|[a;b;c]->three_node ~monoidabc|[a;b;c;d]->four_node~monoidabcd|_->assertfalse(*---------------------------------*)(* front / rear / etc. *)(*---------------------------------*)lethead_digit=function|One(_,a)|Two(_,a,_)|Three(_,a,_,_)|Four(_,a,_,_,_)->aletlast_digit=function|One(_,a)|Two(_,_,a)|Three(_,_,_,a)|Four(_,_,_,_,a)->alettail_digit_node~monoid=function|One_->assertfalse|Two(_,_,a)->one_nodea|Three(_,_,a,b)->two_node~monoidab|Four(_,_,a,b,c)->three_node~monoidabclettail_digit~monoid~measure=function|One_->assertfalse|Two(_,_,a)->one~measurea|Three(_,_,a,b)->two~monoid~measureab|Four(_,_,a,b,c)->three~monoid~measureabcletinit_digit_node~monoid=function|One_->assertfalse|Two(_,a,_)->one_nodea|Three(_,a,b,_)->two_node~monoidab|Four(_,a,b,c,_)->three_node~monoidabcletinit_digit~monoid~measure=function|One_->assertfalse|Two(_,a,_)->one~measurea|Three(_,a,b,_)->two~monoid~measureab|Four(_,a,b,c,_)->three~monoid~measureabctype('a,'rest)view=|Vnil|Vconsof'a*'restletrecview_left_aux:'a'm.monoid:'mmonoid->(('a,'m)node,'m)fg->(('a,'m)node,(('a,'m)node,'m)fg)view=fun~monoid ->function|Nil->Vnil|Singlex->Vcons(x,Nil)|Deep(_,One(_,a),m,sf)->letvcons=matchview_left_aux~monoidmwith|Vnil->to_tree_digit_node~monoidsf|Vcons(a,m')->deep~monoid(to_digit_nodea)m'sfinVcons(a,vcons)|Deep(_,pr,m,sf)->letvcons=deep~monoid(tail_digit_node~monoidpr)msfinVcons(head_digitpr,vcons)letview_left~monoid ~measure=function|Nil->Vnil|Singlex->Vcons(x,Nil)|Deep(_,One(_,a),m,sf)->letvcons=matchview_left_aux~monoidmwith|Vnil->to_tree_digit~monoid~measuresf|Vcons (a,m')->deep~monoid(to_digit_nodea)m'sfinVcons(a,vcons)|Deep(_,pr,m,sf)->letvcons=deep~monoid(tail_digit~monoid~measure pr)msfinVcons(head_digitpr,vcons)letrecview_right_aux:'a'm.monoid:'mmonoid->(('a,'m)node,'m)fg->(('a,'m)node,(('a,'m)node,'m)fg)view=fun~monoid ->function|Nil->Vnil|Singlex->Vcons(x,Nil)|Deep(_,pr,m,One(_,a))->letvcons=matchview_right_aux~monoidmwith|Vnil->to_tree_digit_node~monoidpr|Vcons(a,m')->deep~monoidprm'(to_digit_nodea)inVcons(a,vcons)|Deep(_,pr,m,sf)->letvcons=deep~monoidprm(init_digit_node~monoidsf)inVcons(last_digit sf,vcons)letview_right~monoid~measure=function|Nil->Vnil|Singlex->Vcons(x,Nil)|Deep(_,pr,m,One(_,a))->letvcons=matchview_right_aux~monoidmwith|Vnil->to_tree_digit~monoid~measurepr|Vcons (a,m')->deep~monoidprm'(to_digit_nodea)inVcons(a,vcons)|Deep(_,pr,m,sf)->letvcons=deep~monoidprm(init_digit~monoid~measuresf)inVcons (last_digit sf,vcons)lethead_exn=function|Nil->raiseEmpty|Singlea->a|Deep(_,pr,_,_)->head_digitprlethead=function|Nil->None|Singlea->Somea|Deep(_,pr,_,_)->Some(head_digitpr)letlast_exn=function|Nil->raiseEmpty|Singlea->a|Deep(_,_,_,sf)->last_digitsfletlast=function|Nil->None|Singlea->Somea|Deep(_,_,_,sf)->Some(last_digitsf)lettail~monoid~measuret=match view_left ~monoid ~measuretwith|Vnil->None|Vcons(_,tl)->Sometllettail_exn~monoid~measuret=match view_left ~monoid ~measuretwith|Vnil->raiseEmpty|Vcons(_,tl)->tlletfront~monoid~measuret=match view_left ~monoid ~measuretwith|Vnil->None|Vcons(hd,tl)->Some(tl,hd)letfront_exn~monoid~measuret=match view_left ~monoid ~measuretwith|Vnil->raiseEmpty|Vcons(hd,tl)->(tl,hd)letinit~monoid~measuret=match view_right ~monoid~measuretwith|Vnil->None|Vcons(_,tl)->Sometlletinit_exn~monoid~measuret=match view_right ~monoid~measuretwith|Vnil->raiseEmpty|Vcons(_,tl)->tlletrear~monoid~measuret=match view_right ~monoid~measuretwith|Vnil->None|Vcons(hd,tl)->Some(tl,hd)letrear_exn~monoid~measure t=match view_right ~monoid~measuretwith|Vnil->raiseEmpty|Vcons(hd,tl)->(tl,hd)(*---------------------------------*)(* append *)(*---------------------------------*)letnodes=letadd_digit_todigitl=matchdigitwith|One(_,a)->a::l|Two(_,a,b)->a::b::l|Three(_,a,b,c)->a::b::c::l|Four(_,a,b,c,d)->a::b::c::d::linletrecnodes_aux~monoid~measuretssf2=(* no idea if this should be tail rec *)matchts,sf2with|[],One_->assertfalse|[],Two(_,a,b)|[a],One(_,b)->[node2~monoid~measureab]|[],Three(_,a,b,c)|[a],Two(_,b,c)|[a;b],One(_,c)->[node3~monoid~measureabc]|[],Four(_,a,b,c,d)|[a],Three(_,b,c,d)|[a;b],Two(_,c,d)|[a;b;c],One(_,d)->[node2~monoid~measureab;node2~monoid ~measurecd]|a::b::c::ts,_->node3~monoid~measureabc::nodes_aux~monoid~measuretssf2|[a],Four(_,b,c,d,e)|[a;b],Three(_,c,d,e)->[node3~monoid~measureabc;node2~monoid~measurede]|[a;b],Four(_,c,d,e,f)->[node3~monoid~measureabc;node3~monoid~measuredef]infun ~monoid~measuresf1tssf2->letts=add_digit_to sf1tsinnodes_aux~monoid~measuretssf2letrecapp3:'a'm.monoid:'mmonoid->measure:('a->'m)->('a,'m)fg->'alist->('a,'m)fg->('a,'m)fg=fun~monoid~measuret1eltst2->matcht1,t2with|Nil,_->List.fold_right(funeltacc->cons~monoid~measureaccelt)eltst2|_,Nil->List.fold_left(funaccelt->snoc~monoid ~measureaccelt)t1elts|Singlex1,_->cons~monoid~measure(List.fold_right(funeltacc->cons~monoid~measureaccelt)eltst2)x1|_,Single x2->snoc~monoid~measure (List.fold_left(funaccelt->snoc~monoid ~measureaccelt)t1elts)x2|Deep (_,pr1,m1,sf1),Deep(_,pr2,m2,sf2)->deep~monoidpr1(app3~monoid~measure:measure_nodem1(nodes~monoid~measuresf1eltspr2)m2)sf2letappend~monoid~measuret1t2=app3 ~monoid ~measuret1[]t2(*---------------------------------*)(* reverse *)(*---------------------------------*)(* unfortunately, when reversing, we need to rebuild every annotation
* because the monoid does not have to be commutative *)letreverse_digit_node~monoidrev_a=function|One(_,a)->one_node(rev_aa)|Two(_,a,b)->two_node~monoid(rev_ab)(rev_aa)|Three(_,a,b,c)->three_node~monoid(rev_ac)(rev_ab)(rev_aa)|Four(_,a,b,c,d)->four_node~monoid(rev_ad)(rev_ac)(rev_ab)(rev_a a)letreverse_digit~monoid~measure=function|One_asd->d|Two(_,a,b)->two~monoid~measureba|Three(_,a,b,c)->three~monoid~measurecba|Four(_,a,b,c,d)->four~monoid~measuredcbaletreverse_node_node~monoidrev_a=function|Node2 (_,a,b)->node2_node~monoid(rev_ab)(rev_aa)|Node3(_,a,b,c)->node3_node~monoid(rev_ac)(rev_ab)(rev_aa)letreverse_node~monoid ~measure=function|Node2(_,a,b)->node2~monoid~measureba|Node3(_,a,b,c)->node3~monoid~measurecbaletrecreverse_aux:'a'm.monoid:'mmonoid->(('a,'m)node->('a,'m)node)->(('a,'m)node,'m)fg->(('a,'m)node,'m)fg=fun~monoidreverse_a ->function|Nil->Nil|Singlea->Single(reverse_aa)|Deep(_,pr,m,sf)->letrev_pr=reverse_digit_node~monoid reverse_aprinletrev_sf=reverse_digit_node~monoid reverse_asfinletrev_m=reverse_aux~monoid(reverse_node_node ~monoid(reverse_a))mindeep~monoidrev_sfrev_mrev_prletreverse~monoid ~measure =function|Nil|Single_ast->t|Deep(_,pr,m,sf)->letrev_pr=reverse_digit~monoid~measureprinletrev_sf =reverse_digit ~monoid~measuresfinletrev_m =reverse_aux ~monoid(reverse_node ~monoid~measure)mindeep~monoidrev_sfrev_mrev_pr(*---------------------------------*)(* split *)(*---------------------------------*)type('a,'rest)split=Splitof'rest*'a*'restletsplit_digit~monoid~measurepi=function|One(_,a)->Split([],a,[])|Two(_,a,b)->leti'=monoid.combinei(measurea)inifpi'thenSplit ([],a,[b])elseSplit([a],b,[])|Three(_,a,b,c)->leti'=monoid.combinei(measurea)inifpi'thenSplit ([],a,[b;c])elseleti''=monoid.combinei'(measureb)inifpi''thenSplit([a],b,[c])elseSplit([a;b],c,[])|Four(_,a,b,c,d)->leti'=monoid.combinei(measurea)inifpi'thenSplit ([],a,[b;c;d])elseleti''=monoid.combinei'(measureb)inifpi''thenSplit([a],b,[c;d])elseleti'''=monoid.combinei''(measurec)inif pi'''thenSplit([a;b],c,[d])elseSplit([a;b;c],d,[])letdeep_left~monoid~measureprmsf=matchprwith|[]->(matchview_left~monoid~measure:measure_nodemwith|Vnil->to_tree_digit~monoid~measuresf|Vcons (a,m')->deep~monoid(to_digit_nodea)m'sf)|_->deep ~monoid(to_digit_list~monoid~measurepr)msfletdeep_right ~monoid~measureprmsf=matchsfwith|[]->(matchview_right~monoid~measure:measure_nodemwith|Vnil->to_tree_digit~monoid~measurepr|Vcons (a,m')->deep~monoidprm'(to_digit_nodea))|_->deep~monoidprm(to_digit_list~monoid~measuresf)letrecsplit_tree :'a'm.monoid:'mmonoid->measure:('a->'m)->('m->bool)->'m->('a,'m)fg->('a,('a,'m)fg)split=fun~monoid~measurepi->function|Nil->raiseEmpty|Singlex->Split(Nil,x,Nil)|Deep(_,pr,m,sf)->letvpr=monoid.combinei(measure_digitpr)inifpvprthenletSplit(l,x,r)=split_digit~monoid~measurepiprinSplit(to_tree_list~monoid~measurel,x,deep_left~monoid~measurermsf)elseletvm=monoid.combinevpr(measure_t_node~monoidm)inifpvmthenletSplit(ml,xs,mr)=split_tree~monoid~measure:measure_nodepvprminletSplit(l,x,r)=split_digit~monoid~measurep(monoid.combinevpr(measure_t_node~monoidml))(to_digit_nodexs)inSplit(deep_right~monoid~measureprmll,x,deep_left ~monoid~measure rmrsf)elseletSplit(l,x,r)=split_digit~monoid~measurepvmsfinSplit(deep_right ~monoid~measureprml,x,to_tree_list~monoid~measurer)letsplit~monoid~measureft=matchtwith|Nil->(Nil,Nil)|_->iff(measure_t~monoid~measuret)thenletSplit(l,x,r)=split_tree~monoid~measurefmonoid.zerotin(l,cons~monoid~measurerx)else(t,Nil)(*---------------------------------*)(* lookup *)(*---------------------------------*)(* This is a simplification of splitTree that avoids rebuilding the tree
* two trees around the elements being looked up
* But you can't just find the element, so instead these functions find the
* element _and_ the measure of the elements of the current node that are on
* the left of the element.
*
* (this is needed because in splitTree, at some point, you measure the left
* tree returned by a recursive call, but here we don't have the left tree!)
*)letlookup_digit~monoid~measurepi=function|One(_,a)->monoid.zero,a|Two(_,a,b)->letm_a=measureainleti'=monoid.combineim_ainifpi'thenmonoid.zero,aelsem_a,b|Three(_,a,b,c)->letm_a=measureainleti'=monoid.combineim_ainifpi'thenmonoid.zero,aelseletm_b =measurebinleti''=monoid.combinei'm_binifpi''thenm_a,belsemonoid.combine m_am_b,c|Four (_,a,b,c,d)->letm_a=measureainleti'=monoid.combineim_ainifpi'thenmonoid.zero,aelseletm_b =measurebinleti''=monoid.combinei'm_binifpi''thenm_a,belseletm_c=measurecinlet i'''=monoid.combinei''m_cinifpi'''thenmonoid.combinem_am_b,celsemonoid.combine(monoid.combinem_am_b)m_c,dletlookup_node~monoid~measurepi=function|Node2(_,a,b)->letm_a=measureainleti'=monoid.combineim_ainifpi'thenmonoid.zero,aelsem_a,b|Node3(_,a,b,c)->letm_a=measureainleti'=monoid.combineim_ainifpi'thenmonoid.zero,aelseletm_b =measurebinleti''=monoid.combinei'm_binifpi''thenm_a,belsemonoid.combine m_am_b,cletreclookup_tree:'a'm.monoid:'mmonoid->measure:('a->'m)->('m->bool)->'m->('a,'m)fg->'m*'a=fun~monoid ~measurepi->function|Nil->raiseEmpty|Singlex->monoid.zero,x|Deep(_,pr,m,sf)->letm_pr=measure_digitprinletvpr=monoid.combineim_prinifpvprthenlookup_digit~monoid~measurepiprelseletm_m=measure_t_node ~monoidminletvm=monoid.combinevprm_minifpvmthenletv_left,node=lookup_tree~monoid ~measure:measure_nodepvprminletv,x=lookup_node~monoid~measure p(monoid.combinevprv_left)nodeinmonoid.combine(monoid.combinem_prv_left)v,xelseletv,x=lookup_digit~monoid~measure pvmsfinmonoid.combine (monoid.combinem_prm_m)v,xletlookup~monoid~measurept=snd(lookup_tree~monoid~measurepmonoid.zerot)(*---------------------------------*)(* enumerations *)(*---------------------------------*)type('a,'m)iter=|End|Nextof'a*('a,'m)iter|Digitof('a,'m)digit*('a,'m)iter|Fgof(('a,'m)node,'m)iter*('a,'m)iterletrecto_iter:'a.('a,'m)fg->('a,'m)iter->('a,'m)iter=funtk->match twith|Nil->k|Singlea->Next(a,k)|Deep(_,pr,m,sf)->Digit(pr,Fg(to_itermEnd,Digit(sf,k)))letrecto_iter_backwards:'a.('a,'m)fg->('a,'m)iter->('a,'m)iter=funtk->match twith|Nil->k|Singlea->Next(a,k)|Deep(_,pr,m,sf)->Digit(sf,Fg(to_iter_backwardsmEnd,Digit(pr,k)))(*---------------------------------*)(* conversion *)(*---------------------------------*)letreciter_next:'a.('a,'m)iter->('a*('a,'m)iter)option =function|End->None|Next(v,k)->Some(v,k)|Digit(One(_,a),k)->Some(a,k)|Digit(Two(_,a,b),k)->Some(a,Next(b,k))|Digit(Three(_,a,b,c),k)->Some(a,Next(b,Next(c,k)))|Digit(Four(_,a,b,c,d),k)->Some(a,Next(b,Next(c,Next(d,k))))|Fg(node_iter,k)->matchiter_nextnode_iterwith|None->iter_nextk|Some(Node2(_,a,b),k_node)->Some(a,Next(b,Fg(k_node,k)))|Some(Node3(_,a,b,c),k_node)->Some(a,Next(b,Next(c,Fg(k_node,k))))letreciter_next_backwards:'a.('a,'m)iter->('a*('a,'m)iter)option =function|End->None|Next(v,k)->Some(v,k)|Digit(One(_,a),k)->Some(a,k)|Digit(Two(_,a,b),k)->Some(b,Next(a,k))|Digit(Three(_,a,b,c),k)->Some(c,Next(b,Next(a,k)))|Digit(Four(_,a,b,c,d),k)->Some(d,Next(c,Next(b,Next(a,k))))|Fg(node_iter,k)->matchiter_next_backwardsnode_iterwith|None->iter_next_backwardsk|Some(Node2(_,a,b),k_node)->Some(b,Next(a,Fg(k_node,k)))|Some(Node3(_,a,b,c),k_node)->Some(c,Next(b,Next(a,Fg(k_node,k))))letenumt=BatEnum.unfold(to_iter tEnd)iter_nextletbackwardst=BatEnum.unfold(to_iter_backwardstEnd)iter_next_backwardsletof_enum~monoid~measureenum=BatEnum.fold(fun telt->snoc~monoid~measuretelt)emptyenumletof_backwards ~monoid~measureenum=BatEnum.fold(fun telt->cons~monoid~measuretelt)emptyenumletto_listt=BatList.of_backwards(backwardst)letto_list_backwardst=BatList.of_backwards(enumt)letof_list~monoid ~measurel=List.fold_left (funtelt->snoc~monoid~measuretelt)emptylletof_list_backwards~monoid~measurel=List.fold_left (funtelt->cons~monoid~measuretelt)emptyl(*---------------------------------*)(* classic traversals *)(*---------------------------------*)letiterft=fold_left(fun()elt->felt)()tletiter_rightft=fold_right(fun()elt->felt)()tletmap~monoid~measureft=(* suboptimal when themeasure does not depend on 'a *)fold_left(funaccelt->snoc~monoid~measureacc(felt))empty tletmap_right~monoid~measureft=fold_right(funaccelt->cons~monoid~measureacc(felt))empty t(*---------------------------------*)(* misc *)(*---------------------------------*)letmeasure=measure_t(* no defined because many local variables are
* already called measure, so forgetting to bind
* them would cause weird type errors if this
* definition was in the scope *)letsizet=fold_left(funacc_->acc+1)0tletprint?first?last?sepfocx=BatEnum.print?first?last?sepfoc(enumx)letcomparecmpt1t2=letrecloop cmp iter1iter2=match iter_nextiter1,iter_nextiter2with|None,None->0|Some_,None->1|None,Some_->-1|Some(e1,iter1),Some(e2,iter2)->letc=cmpe1 e2inifc<>0thencelseloopcmpiter1iter2inloopcmp(to_iter t1 End)(to_itert2End)let equaleqt1t2=letrecloopeqiter1 iter2=match iter_nextiter1,iter_nextiter2with|None,None->true|Some_,None->false|None,Some_->false|Some(e1,iter1),Some(e2,iter2)->eqe1e2&&loop eqiter1iter2inloopeq(to_iter t1End)(to_itert2End)(* this function does as of_list, but, by using concatenation,
* it generates trees with some Node2 (which are never generated
* by of_list) *)letof_list_for_test~monoid~measurel=leti=Random.int(List.lengthl+1)inletl1,l2=BatList.split_atilinappend~monoid~measure(of_list~monoid~measurel1)(of_list~monoid~measurel2)endtypenat=intlet nat_plus_monoid ={zero=0;combine=(+);}letsize_measurer=fun_->1type('a,'m)fg=('a,nat)Generic.fgtype'at=('a,nat)fgletlast_exn=Generic.last_exn(*$Q last_exn
(Q.list Q.int) (fun l -> \
(try Some (last_exn (of_list_for_test l)) with Empty -> None) \
= (try Some (BatList.last l) with Invalid_argument _ -> None))
*)(* this T test is just in case the empty list was not generated by the
* test above *)(*$T last_exn
try ignore (last_exn empty); false with Empty -> true
*)lethead_exn=Generic.head_exn(*$Q head_exn
(Q.list Q.int) (fun l -> \
(try Some (head_exn (of_list_for_test l)) with Empty -> None) \
= (try Some (BatList.hd l) with Failure _ -> None))
*) (*$T head_exn
try ignore (head_exn empty); false with Empty -> true
*)letlast=Generic.last(*$Q last
(Q.list Q.int) (fun l -> last (of_list_for_test l) \
= (try Some (BatList.last l) with Invalid_argument _ -> None))
*)(*$T last
last empty = None
*)lethead=Generic.head(*$Q head
(Q.list Q.int) (fun l -> head (of_list_for_test l) \
= (try Some (BatList.hd l) with Failure _ -> None))
*)(*$T head
head empty = None
*)letsingleton=Generic.singleton(*$T singleton
to_list (verify_measure (singleton 78)) = [78]
*)letempty=Generic.empty(*$T empty
to_list (verify_measure empty) = []
*)letis_empty=Generic.is_empty(*$Q is_empty
(Q.list Q.int) (fun l -> is_empty (verify_measure (of_list_for_test l)) = (l = []))
*)letfold_left=Generic.fold_left(* here we test that the accumulator is not lost somewhere in the fold by
* using the count the elements of the sequence and side effects to check
* that it goes left to right *)(*$Q fold_left
(Q.list Q.int) (fun l -> \
let make_bf () = \
let b = Buffer.create 10 in \
b, (fun acc elt -> Printf.bprintf b "%d" elt; acc + 1) \
in \
let b1, f1 = make_bf () in let b2, f2 = make_bf () in \
let count1 = fold_left f1 0 (of_list_for_test l) in \
let count2 = BatList.fold_left f2 0 l in \
count1 = count2 && Buffer.contents b1 = Buffer.contents b2)
*)letfold_right=Generic.fold_right(*$Q fold_right
(Q.list Q.int) (fun l -> \
let make_bf () = \
let b = Buffer.create 10 in \
b, (fun acc elt -> Printf.bprintf b "%d" elt; acc + 1) \
in \
let b1, f1 = make_bf () in let b2, f2 = make_bf () in \
let count1 = fold_right f1 0 (of_list_for_test l) in \
let count2 = BatList.fold_right (fun elt acc -> f2 acc elt) l 0 in \
count1 = count2 && Buffer.contents b1 = Buffer.contents b2)
*)letenum=Generic.enum(*$Q enum
(Q.list Q.int) (fun l -> \
BatList.of_enum (enum (verify_measure (of_list_for_test l))) = l)
*)letbackwards=Generic.backwards(*$Q backwards
(Q.list Q.int) (fun l -> \
BatList.of_enum (backwards (verify_measure (of_list_for_test l))) = List.rev l)
*)letto_list=Generic.to_list(*$Q to_list
(Q.list Q.int) (fun l -> \
to_list (verify_measure (of_list l)) = l)
(Q.list Q.int) (fun l -> \
to_list (verify_measure (of_list_backwards l)) = List.rev l)
(Q.list Q.int) (fun l -> \
to_list (verify_measure (of_enum (BatList.enum l))) = l)
(Q.list Q.int) (fun l -> \
to_list (verify_measure (of_backwards (BatList.enum l))) = List.rev l)
*)letto_list_backwards=Generic.to_list_backwards(*$Q to_list_backwards
(Q.list Q.int) (fun l -> to_list_backwards (verify_measure (of_list_for_test l)) = List.rev l)
*)letiter=Generic.iter(*$Q iter
(Q.list Q.int) (fun l -> \
let make_bf () = \
let b = Buffer.create 10 in \
b, (fun elt -> Printf.bprintf b "%d" elt) \
in let b1, f1 = make_bf () in let b2, f2 = make_bf () in \
iter f1 (of_list_for_test l); BatList.iter f2 l; \
Buffer.contents b1 = Buffer.contents b2)
*)letiter_right=Generic.iter_right(*$Q iter_right
(Q.list Q.int) (fun l -> \
let make_bf () = \
let b = Buffer.create 10 in \
b, (fun elt -> Printf.bprintf b "%d" elt) \
in let b1, f1 = make_bf () in let b2, f2 = make_bf () in \
iter_right f1 (of_list_for_test l); BatList.iter f2 (BatList.rev l); \
Buffer.contents b1 = Buffer.contents b2)
*)type('wrapped_type,'a,'m)wrap='wrapped_typeletconstx=Generic.cons ~monoid:nat_plus_monoid~measure:size_measurertx(*$Q cons
(Q.pair (Q.list Q.int) Q.int) (fun (l,i) -> \
to_list (verify_measure (cons (of_list_for_test l) i)) = i :: l)
*)letsnoctx=Generic.snoc~monoid:nat_plus_monoid~measure:size_measurertx(*$Q snoc
(Q.pair (Q.list Q.int) Q.int) (fun (l,i) -> \
to_list (verify_measure (snoc (of_list_for_test l) i)) = BatList.append l [i])
*)letfrontt=Generic.front~monoid:nat_plus_monoid~measure:size_measurert(*$Q front
(Q.list Q.int) (fun l -> (match front (of_list_for_test l) with \
None -> [] | Some (t, hd) -> hd :: to_list (verify_measure t)) = l)
*)lettailt=Generic.tail~monoid:nat_plus_monoid~measure:size_measurert(*$Q tail
(Q.list Q.int) (fun l -> (match tail (of_list_for_test l) with \
None -> None | Some t -> Some (to_list (verify_measure t))) \
= (match l with [] -> None | _ :: t -> Some t))
*)letinitt=Generic.init~monoid:nat_plus_monoid~measure:size_measurert(*$Q init
(Q.list Q.int) (fun l -> (match init (of_list_for_test l) with \
None -> None | Some init -> Some (to_list (verify_measure init))) \
= (match l with [] -> \
None | _ :: _ -> Some (fst (BatList.split_at (List.length l - 1) l))))
*)letreart=Generic.rear~monoid:nat_plus_monoid~measure:size_measurert(*$Q rear
(Q.list Q.int) (fun l -> (match rear (of_list_for_test l) with \
None -> [] | Some (init, last) -> \
BatList.append (to_list (verify_measure init)) [last]) = l)
*)letfront_exnt=Generic.front_exn~monoid:nat_plus_monoid~measure:size_measurert(*$Q front_exn
(Q.list Q.int) (fun l -> (try let tl, hd = front_exn (of_list_for_test l) in \
hd :: to_list (verify_measure tl) with Empty -> []) = l)
*)lettail_exnt=Generic.tail_exn~monoid:nat_plus_monoid~measure:size_measurert(*$Q tail_exn
(Q.list Q.int) (fun l -> \
(try Some (to_list (verify_measure (tail_exn (of_list_for_test l)))) with \
Empty -> None) = (match l with [] -> None | _ :: t -> Some t))
*)letinit_exnt=Generic.init_exn~monoid:nat_plus_monoid~measure:size_measurert(*$Q init_exn
(Q.list Q.int) (fun l -> \
(try Some (to_list (verify_measure (init_exn (of_list_for_test l)))) with \
Empty -> None) = (match l with [] -> None | _ :: _ -> \
Some (fst (BatList.split_at (List.length l - 1) l))))
*)letrear_exnt=Generic.rear_exn~monoid:nat_plus_monoid~measure:size_measurert(*$Q rear_exn
(Q.list Q.int) (fun l -> (try let init, last = rear_exn (of_list_for_test l) in \
BatList.append (to_list (verify_measure init)) [last] with Empty -> []) = l)
*)letappendt1t2=Generic.append~monoid:nat_plus_monoid~measure:size_measurert1t2(*$Q append
(Q.pair (Q.list Q.int) (Q.list Q.int)) (fun (l1, l2) -> \
to_list (verify_measure (append (of_list_for_test l1) (of_list_for_test l2))) \
= BatList.append l1 l2)
*)letmeasuret=Generic.measure~monoid:nat_plus_monoid~measure:size_measurertletsize=measure(* O(1) this time *)(*$Q size
(Q.list Q.int) (fun l -> List.length l = size (of_list_for_test l))
*)letreverset=Generic.reverse~monoid:nat_plus_monoid~measure:size_measurert(*$Q reverse
(Q.list Q.int) (fun l -> \
to_list (verify_measure (reverse (of_list_for_test l))) \
= BatList.rev l)
*)letsplitft=Generic.split~monoid:nat_plus_monoid~measure:size_measurerftletsplit_atti=ifi<0||i>=sizettheninvalid_arg"FingerTree.split_at: Index out of bounds";split(funindex->i<index)t(*$T split_at
let n = 50 in \
let l = BatList.init n (fun i -> i) in \
let t = of_list_for_test l in let i = ref (-1) in \
BatList.for_all (fun _ -> incr i; let t1, t2 = split_at t !i in \
let l1, l2 = BatList.split_at !i l in \
to_list (verify_measure t1) = l1 && to_list (verify_measure t2) = l2) l
try ignore (split_at empty 0); false with Invalid_argument _ -> true
*)letlookupft=Generic.lookup~monoid:nat_plus_monoid~measure:size_measurerftletgetti=ifi<0||i>=sizettheninvalid_arg"FingerTree.get: Index out of bounds";lookup(funindex->i<index)t(*$T get
letn= 50 in \
let l = BatList.init n (fun i -> i) in \
let t = of_list_for_test l in let i = ref (-1) in \
BatList.for_all (fun elt -> incr i; elt = get t !i) l
try ignore (get (singleton 1) 1); false with Invalid_argument _ -> true
try ignore (get (singleton 1) (-1)); false with Invalid_argument _ -> true
*)letsettiv=ifi<0||i>=sizettheninvalid_arg"FingerTree.set: Index out of bounds";letleft,right=split_attiinappend(snocleftv)(tail_exnright)(*$T set
to_list (set (snoc (snoc (snoc empty 1) 2) 3) 1 4) = [1; 4; 3]
to_list (set (snoc (snoc (snoc empty 1) 2) 3) 0 4) = [4; 2; 3]
to_list (set (snoc (snoc (snoc empty 1) 2) 3) 2 4) = [1; 2; 4]
try ignore (set (snoc (snoc (snoc empty 1) 2) 3) (-1) 4); false with Invalid_argument _ -> true
try ignore (set (snoc (snoc (snoc empty 1) 2) 3) 3 4); false with Invalid_argument _ -> true
*)letupdatetif=setti(f(getti))(*$T updateto_list(verify_measure (update (snoc (snoc (snoc empty 1) 2) 3) 1 (fun x -> x + 1))) = [1; 3; 3]
to_list (verify_measure (update (snoc (snoc (snoc empty 1) 2) 3) 0 (fun x -> x + 1))) = [2; 2; 3]
to_list (verify_measure (update (snoc (snoc (snoc empty 1) 2) 3) 2 (fun x -> x + 1))) = [1; 2; 4]
try ignore (update (snoc (snoc (snoc empty 1) 2) 3) (-1) (fun x -> x + 1)); false with Invalid_argument _ -> true
try ignore (update (snoc (snoc (snoc empty 1) 2) 3) 3 (fun x -> x + 1)); false with Invalid_argument _ -> true
*)letof_enume=Generic.of_enum~monoid:nat_plus_monoid~measure:size_measurereletof_listl=Generic.of_list~monoid:nat_plus_monoid~measure:size_measurerlletof_backwardse=Generic.of_backwards~monoid:nat_plus_monoid~measure:size_measurereletof_list_backwardsl=Generic.of_list_backwards~monoid:nat_plus_monoid~measure:size_measurerlletof_list_for_testl=Generic.of_list_for_test~monoid:nat_plus_monoid~measure:size_measurerlletmapft=Generic.map~monoid:nat_plus_monoid~measure:size_measurerft(*$Q map
(Q.list Q.int)(fun l -> \
let make_bf () = \
let b = Buffer.create 10 in \
b, (fun elt -> Printf.bprintf b "%d" elt; elt + 1) \
in \
let b1, f1 = make_bf () in let b2, f2 = make_bf () in \
let res1 = map f1 (of_list_for_test l) in let res2 = BatList.map f2 l in \
to_list (verify_measure res1) = res2 && Buffer.contents b1 = Buffer.contents b2)
*)letmap_rightft=Generic.map_right~monoid:nat_plus_monoid~measure:size_measurerft(*$Q map_right
(Q.listQ.int) (fun l -> \
let make_bf () = \
let b = Buffer.create 10 in \
b, (fun elt -> Printf.bprintf b "%d" elt; elt + 1) \
in \
let b1, f1 = make_bf () in let b2, f2 = make_bf () in \
let res1 = map_right f1 (of_list_for_test l) in \
let res2 = List.rev (BatList.map f2 (List.rev l)) in \
to_list (verify_measure res1) = res2 && Buffer.contents b1 = Buffer.contents b2)
*)letprint=Generic.printletcompare=Generic.compareletequal=Generic.equalletcheck_measurest=Generic.check_measures~monoid:nat_plus_monoid~measure:size_measurer~eq:BatInt.(=)tletverify_measuret=ifnot(check_measurest)thenfailwith "Invariants not verified";tletinvariantst=assert(check_measurest)