1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071openBatteries(** The normal haskell zip that throws no exception *)letreccombine_shortl1l2=matchl1,l2with|x1::l1,x2::l2->(x1,x2)::combine_shortl1l2|_,_->[]letassoc_eq_opt(eq:'a->'a->bool)(x:'a)(ys:('a*'b)list):('boption)=letopenGobOption.Syntaxinlet+(_,y)=List.find_opt(fun(x',_)->eqxx')ysinyletrecfold_left3faccl1l2l3=matchl1,l2,l3with|[],[],[]->acc|x1::l1,x2::l2,x3::l3->fold_left3f(faccx1x2x3)l1l2l3|_,_,_->invalid_arg"GobList.fold_left3"letrecfor_all3fl1l2l3=matchl1,l2,l3with|[],[],[]->true|x1::l1,x2::l2,x3::l3->fx1x2x3&&(for_all3[@tailcall])fl1l2l3|_,_,_->invalid_arg"GobList.for_all3"letrecfold_while_some(f:'a->'b->'aoption)(acc:'a)(xs:'blist):'aoption=matchxswith|[]->Someacc|x::xs->beginmatchfaccxwith|Someacc'->fold_while_somefacc'xs|None->Noneendletequal=List.eq(** [remove_common_prefix eq l1 l2] removes the common prefix ([p]) of [l1] and [l2] and
returns the rest of both lists a pair [(l1', l2')].
Formally, [p @ l1' = l1] and [p @ l2' = l2] such that [p] has maximal length.
This can be used to check being a prefix in both directions simultaneously:
- if [l1' = []], then [l1] is a prefix of [l2],
- if [l2' = []], then [l2] is a prefix of [l1].
In other cases, the common prefix is not returned (i.e. reconstructed) for efficiency reasons.
@param eq equality predicate for elements *)letrecremove_common_prefixeql1l2=matchl1,l2with|x1::l1',x2::l2'wheneqx1x2->remove_common_prefixeql1'l2'|_,_->(l1,l2)(** Given a predicate and a list, returns two lists [(l1, l2)].
[l1] contains the prefix of the list until the last element that satisfies the predicate, [l2] contains all subsequent elements. The order of elements is preserved. *)letuntil_last_with(pred:'a->bool)(xs:'alist)=letrecuntil_last_helperlastseen=function|[]->List.revlast,List.revseen|h::t->ifpredhthenuntil_last_helper(h::seen@last)[]telseuntil_last_helperlast(h::seen)tinuntil_last_helper[][]xs(** Open this to use applicative functor/monad syntax for {!list}. *)moduleSyntax=struct(* Applicative functor. *)let(let+)xf=List.mapfxlet(and+)=List.cartesian_product(* Monad *)let(let*)xf=List.concat_mapfxlet(and*)=(and+)let(>>=)xf=List.concat_mapfxend