123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567(*
* Copyright (C) 2009 Jeremie Dimino
* Copyright (C) 2017 Simon Cruanes, INRIA
*
* 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
*)##V>=5##modulePervasives=Stdlibtype'anode=##V>=4.7##'aStdlib.Seq.node=|Nil|Consof'a*'at##V<4.7##and'at=unit->'anode##V>=4.7##and'at='aStdlib.Seq.ttype 'amappable='atletnil()=Nilletconses()=Cons(e,s)letlengths=letrecauxaccs=match s()with|Nil->acc|Cons(_,s)->aux(acc+1)sinaux0sletrecenum_of_refr=BatEnum.make~next:(fun_->match!r()with|Nil->raiseBatEnum.No_more_elements|Cons(e,s)->r:=s;e)~count:(fun_->length!r)~clone:(fun_->enum_of_ref (ref!r))letenums=enum_of_ref(refs)lethds=matchs()with|Nil->invalid_arg"Seq.hd"|Cons(e,_s)->elettls=matchs()with|Nil->invalid_arg"Seq.tl"|Cons(_e,s)->sletfirsts=matchs()with|Nil->invalid_arg"Seq.first"|Cons(e,_s)->eletlasts=letrecauxes=matchs()with|Nil->e|Cons(e,s)->auxesinmatchs()with|Nil->invalid_arg"Seq.last"|Cons(e,s)->auxesletis_empty s=s()=Nilletatsn=letrecauxsn=matchs()with|Nil->invalid_arg"Seq.at"|Cons(e,s)->ifn=0theneelseauxs(n-1)inifn<0theninvalid_arg"Seq.at"elseauxsnletrecappends1s2()=matchs1()with|Nil->s2()|Cons(e,s1)->Cons(e,appends1s2)letconcat s=letrecauxcurrentrest()=matchcurrent()with|Cons(e,s)->Cons(e,auxsrest)|Nil->matchrest()with|Cons(e,s)->auxes()|Nil->Nilinauxnilsletflatten=concatletmakene=letrecauxn()=ifn=0thenNilelseCons(e,aux(n-1))inifn<0theninvalid_arg"Seq.make"elseauxnletinitnf=letrecauxi()=ifi=nthenNilelseCons(fi,aux(i+1))inifn<0theninvalid_arg"Seq.init"elseaux0letof_listl=letrecauxl()=matchlwith|[]->Nil|x::l'->Cons(x,aux l')inauxlletempty=nil(*$T empty
length empty = 0 *)letreturnx=consxempty(*$T return
length (return 123) = 1
at (return 123) 0 = 123
equal (return 123) (of_list[123])
*)letrecunfoldfu=matchfuwith|Some(v,r)->(fun()->Cons(v,unfoldfr))|None->nil(*$T unfold
equal (unfold (fun x -> if x = 0 then None else Some (x, x-1)) 5) (of_list [5;4;3;2;1])
fold_left (fun a b -> b :: a) [] (unfold (fun x -> if x = 0 then None else Some (x, x-1)) 5) =[1;2;3;4;5]
*)letreciterfs=matchs()with|Nil->()|Cons(e,s)->fe;iterfsletiterifs=letreciterifis=matchs()with|Nil->()|Cons(e,s)->fie;iterif(i+1)siniterif0s(*$T iteri
try iteri (fun i x -> if i<>x then raise Exit) (of_list [0;1;2;3]); true \
with Exit -> false
*)letreciter2 fs1s2=matchs1(),s2()with|Nil,_|_,Nil->()|Cons(x1,s1'),Cons(x2,s2')->fx1x2;iter2fs1's2'(*$T iter2
let r = ref 0 in \
iter2 (fun i j -> r := !r + i*j) (of_list [1;2]) (of_list [3;2;1]); \
!r= 3 + 2*2
*)letrecmapfs()=matchs()with|Nil->Nil|Cons(x,s)->Cons(fx,mapfs)letflat_mapfs=flatten(mapfs)(*$T flat_map
equal (flat_map of_list (of_list [[1;2;3];[4;5;6]])) (of_list [1;2;3;4;5;6])
*)(* alias *)letconcat_map =flat_mapletmapifs=letrecmapifis()=matchs()with|Nil->Nil|Cons(x,s)->Cons(fix,mapif(i+1)s)inmapif0s(*$T mapi
equal (of_list [0;0;0;0]) \
(mapi (fun i x -> i - x) (of_list[0;1;2;3]))
*)letrecmap2fs1s2()=matchs1(),s2()with|Nil,_|_,Nil->Nil|Cons(x1,s1'),Cons(x2,s2')->Cons(fx1x2,map2fs1's2')(*$T map2
equal (map2 (+) (of_list [1;2;3]) (of_list [3;2])) \
(of_list[4;4]) *)letrecfold_leftfaccs=matchs()with|Nil->acc|Cons(e,s)->fold_leftf(facce)sletrecfold_rightfsacc=matchs()with|Nil->acc|Cons(e,s)->fe(fold_right fsacc)letreducefs=matchs()with|Nil->invalid_arg"Seq.reduce"|Cons(e,s)->fold_leftfesletmaxs=matchs()with|Nil->invalid_arg"Seq.max"|Cons(e,s)->fold_leftPervasives.maxesletmins=matchs()with|Nil->invalid_arg"Seq.min"|Cons(e,s)->fold_leftPervasives.min esletequal?(eq=(=))s1s2 =letrecrecurse eqs1s2=matchs1(),s2()with|Nil,Nil->true|Nil,Cons_|Cons_,Nil ->false|Cons(x1,s1'),Cons(x2,s2')->eqx1x2&&recurseeqs1' s2'inrecurseeqs1s2(*$T of_list
equal (of_list [1;2;3]) (nil |> cons 3 |> cons 2 |>cons 1)
*)letrecfor_allfs=matchs()with|Nil->true|Cons(e,s)->fe&&for_allfsletrecexistsfs=matchs()with|Nil->false|Cons(e,s)->fe||existsfsletmemes=exists((=)e)sletrecfindfs=matchs()with|Nil->None|Cons(e,s)->iffethenSomeeelsefindfsletrecfind_mapfs=matchs()with|Nil->None|Cons(e,s)->matchfewith|None->find_mapfs|x->xletrecfilterfs()=matchs()with|Nil->Nil|Cons(e,s)->iffethenCons(e,filterfs)elsefilterfs()letrecfilter_mapfs()=matchs()with|Nil->Nil|Cons(e,s)->matchfewith|None->filter_mapfs()|Somee->Cons(e,filter_mapfs)letassockeys=find_map(fun(k,v)->ifk=keythenSomevelseNone)slet rectakens()=ifn<=0thenNilelsematchs()with|Nil->Nil|Cons(e,s)->Cons(e,take(n-1)s)letrecdropns=ifn<=0thenselsematchs()with|Nil->nil|Cons(_e,s)->drop(n-1)sletrectake_whilefs()=matchs()with|Nil->Nil|Cons(e,s)->iffethenCons(e,take_whilefs)elseNilletrecdrop_whilefs=matchs()with|Nil->nil|Cons(e,s)->iffethendrop_whilefselseconsesletsplits=(mapfsts,mapsnds)letrec combines1s2()=matchs1(),s2()with|Nil,Nil->Nil|Cons(e1,s1),Cons(e2,s2)->Cons((e1,e2),combines1 s2)|_->invalid_arg"Seq.combine"letprint?(first="[")?(last="]")?(sep="; ")print_aouts=matchs()with|Nil->BatInnerIO.nwriteoutfirst;BatInnerIO.nwriteoutlast|Cons(e,s)->matchs()with|Nil->BatPrintf.fprintfout"%s%a%s"firstprint_aelast|_->BatInnerIO.nwriteoutfirst;print_aoute;iter(BatPrintf.fprintfout"%s%a"sepprint_a)s;BatInnerIO.nwriteoutlastletto_buffer?(first="[")?(last="]")?(sep=";")to_strbuffs=matchs()with|Nil->(Buffer.add_stringbufffirst;Buffer.add_stringbufflast)|Cons(e,s)->matchs()with|Nil->(Buffer.add_stringbufffirst;Buffer.add_stringbuff(to_stre);Buffer.add_stringbufflast)|_->Buffer.add_stringbufffirst;Buffer.add_stringbuff(to_stre);iter(fune->Buffer.add_stringbuffsep;Buffer.add_stringbuff(to_stre))s;Buffer.add_stringbufflastletto_string?(first="[")?(last="]")?(sep=";")to_strs=letbuff=Buffer.create80into_buffer~first~last~septo_strbuffs;Buffer.contentsbuff(*$T to_string
to_string string_of_int (of_list [1;2;3]) = "[1;2;3]"
to_string ~first:"{" ~sep:"," ~last:"}" string_of_int (of_list [1;2;3]) = "{1,2,3}"
to_string string_of_int (of_list []) = "[]"
*)letof_string?(first="[")?(last="]")?(sep=";")of_strs=ifnot(BatString.starts_withsfirst)thenraise(Invalid_argument("Seq.of_string: wrong prefix: "^first^" not prefix of "^s));ifnot (BatString.ends_withslast)thenraise(Invalid_argument("Seq.of_string: wrong suffix:"^last^" not suffix of "^s));letprfx_len=String.lengthfirstinletsufx_len=String.lengthlastinletn=String.lengthsinifn=prfx_len+sufx_lenthennilelseletbody =BatString.chop~l:prfx_len~r:sufx_lensinletstrings=BatString.nsplit~by:sepbodyinof_list (List.mapof_strstrings)(*$T of_string
equal (of_string int_of_string "[1;2;3]") (of_list [1;2;3])
equal (of_string int_of_string "[]") (of_list [])
equal (of_string ~first:"{" ~sep:"," ~last:"}" int_of_string "{1,2,3}") (of_list [1;2;3])
try equal (of_string ~first:"{" int_of_string "[1;2;3]") (of_list []) with (Invalid_argument _) -> true
try equal (of_string ~last:"}" int_of_string "[1;2;3]") (of_list []) with (Invalid_argument _) -> true
*)##V>=4.14##letuncons=Stdlib.Seq.uncons##V>=4.14##letfold_lefti =Stdlib.Seq.fold_lefti##V>=4.14##letfold_left2=Stdlib.Seq.fold_left2##V>=4.14##letfor_all2=Stdlib.Seq.for_all2##V>=4.14##letexists2 =Stdlib.Seq.exists2##V>=4.14##letcompare =Stdlib.Seq.compare##V>=4.14##letrepeat=Stdlib.Seq.repeat##V>=4.14##letforever=Stdlib.Seq.forever##V>=4.14##letcycle=Stdlib.Seq.cycle##V>=4.14##letiterate =Stdlib.Seq.iterate##V>=4.14##letscan=Stdlib.Seq.scan##V>=4.14##letgroup=Stdlib.Seq.group##V>=4.14##letmemoize=Stdlib.Seq.memoize##V>=4.14##exception Forced_twice =Stdlib.Seq.Forced_twice##V>=4.14##letonce=Stdlib.Seq.once##V>=4.14##lettranspose=Stdlib.Seq.transpose##V>=4.14##letzip=Stdlib.Seq.zip##V>=4.14##letinterleave=Stdlib.Seq.interleave##V>=4.14##letsorted_merge =Stdlib.Seq.sorted_merge##V>=4.14##letproduct=Stdlib.Seq.product##V>=4.14##letmap_product =Stdlib.Seq.map_product##V>=4.14##letunzip=Stdlib.Seq.unzip##V>=4.14##letpartition_map=Stdlib.Seq.partition_map##V>=4.14##letpartition=Stdlib.Seq.partition##V>=4.14##letof_dispenser=Stdlib.Seq.of_dispenser##V>=4.14##letto_dispenser=Stdlib.Seq.to_dispenser##V>=4.14##letints=Stdlib.Seq.ints##V>=4.14##letequal_stdlib=Stdlib.Seq.equal##V>=5.1##letfind_index=Stdlib.Seq.find_index##V>=5.1##letfind_mapi=Stdlib.Seq.find_mapimoduleInfix=struct(** Infix operatorsmatching thoseprovided by {!BatEnum.Infix} *)let(--)ab=ifb<athennilelseinit(b-a+1)(funx->a+x)let(--^)ab=a--(b-1)let(--.)(a,step)b=let n=int_of_float((b-.a)/.step)+1inifn<0thennilelseinitn(funi->float_of_inti*.step+.a)let(---)ab=letn=abs(b-a)inifb<atheninitn(funx->a-x)elsea--blet(--~)ab=mapChar.chr(Char.codea--Char.codeb)let(//)sf=filterfslet(/@)sf=mapfslet(@/)=maplet(//@)sf=filter_mapfslet(@//)=filter_mapendincludeInfixmoduleExceptionless=struct(*$< Exceptionless *)(* This function could be used to eliminate a lot of duplicate code below...
letexceptionless_arg f se=
try Some (f s)
with Invalid_argument e -> None
*)lethds=trySome(hds)withInvalid_argument_->Nonelettls=trySome(tls)withInvalid_argument_->Noneletfirsts=trySome(firsts)withInvalid_argument_->Noneletlasts=trySome(lasts)withInvalid_argument_->Noneletatsn=trySome(atsn)withInvalid_argument_->None(*
let make n e=
try Some (make n e)
with Invalid_argument _ -> None
let init n e =
try Some (init n e) with Invalid_argument _ -> None
*)letreducefs=trySome(reducefs)withInvalid_argument_->Noneletmaxs=trySome(maxs)withInvalid_argument_->Noneletmins=trySome(mins)withInvalid_argument_->Noneletreccombines1s2()=matchs1(),s2()with|Nil,Nil->Nil|Cons(e1,s1),Cons(e2,s2)->Cons((e1,e2),combines1s2)|_->Nil(*$T combine
equal (combine (of_list [1;2]) (of_list ["a";"b"])) (of_list [1,"a"; 2,"b"])
equal (combine (of_list [1;2]) (of_list ["a";"b";"c"])) (of_list [1,"a"; 2,"b"])
equal (combine (of_list [1;2;3]) (of_list ["a";"b"])) (of_list [1,"a"; 2,"b"])
*)(*$>*)end