Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file miscellany.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117openPpxlibopenStdLabels(** {1 Miscellany} *)(** Alias for [Stdio.printf] *)letprintf=Stdio.printf(** Constructs a [loc] given some payload [txt] and a location [loc] *)letwith_loc(txt:'a)~(loc:Location.t):'aLocation.loc={txt;loc}(** Strips the location info from a value of type ['a loc] *)letno_loc(a_loc:'aLocation.loc):'a=a_loc.txt(** Maps a function [f] over a value of type ['a loc],
returning a value of type ['b loc] *)letmap_with_loc~(f:'a->'b)(alpha:'aLocation.loc):'bLocation.loc=leta=alpha.txtin{alphawithtxt=fa}(** Takes the maximum of two [Location.t] values using Ppxlib's in-built
[Location.compare] function *)letmax_loc(l1:Location.t)(l2:Location.t):Location.t=ifLocation.comparel1l2>=0thenl1elsel2(** Maps a function component-wise over a pair *)letmap2~f(a1,a2)=(fa1,fa2)(** Maps a function [f] over 4 lists that must have the same length
- Implementation adapted from [List.map2] in the standard library
- Raises [Invalid_argument] if the 4 lists have different lengths *)let[@tail_mod_cons]reclist_map4~(f:'a->'b->'c->'d->'e)(l1:'alist)(l2:'blist)(l3:'clist)(l4:'dlist):'elist=match(l1,l2,l3,l4)with|[],[],[],[]->[]|[a],[b],[c],[d]->letr1=fabcdin[r1]|x1::x2::xs,y1::y2::ys,z1::z2::zs,w1::w2::ws->letr1=fx1y1z1w1inletr2=fx2y2z2w2inr1::r2::list_map4~fxsyszsws|_,_,_,_->invalid_arg"list_map3"(** Converts a 4-tuple to a pair *)lettuple4_to_pair(a,b,_,_)=(a,b)(** Checks if a list is empty
- Backwards-compatible version of [List.is_empty],
which is only available in OCaml 5.1 and newer *)letlist_is_empty(lst:'alist):bool=matchlstwith|[]->true|_->false(** Takes the disjunction of a Boolean list
- The empty list corresponds to false
- Reimplementation of the [or] function in
Haskell's [GHC.Prelude] *)letreclist_or(xs:boollist):bool=matchxswith|[]->false|x::xs->x||list_orxs(** Retrieves all elements of a list except the last one *)letrecremove_last(lst:'alist):'alist=matchlstwith|[]|[_]->[]|x::xs->x::remove_lastxs(** Returns the final element of a list (if one exists)
- Raises an exception if the list is empty *)letrecget_last(lst:'alist):'a=matchlstwith|[]->failwith"List is empty"|[x]->x|_::xs->get_lastxs(** Swaps the keys & values of an association list.
- Note: bijectivity is not guaranteed since keys may appear more than once
in the input association list.
- Adapted from Jane street's [Base.List.Assoc.inverse] function *)letinvert_assoc_list(lst:('a*'b)list):('b*'a)list=List.map~f:(fun(x,y)->(y,x))lst(** [merge_list_with_assoc_list xs yzs ~eq] takes [xs : 'a list]
and an association list [yzs : ('b * 'c) list], and creates a
new association list of type [('a * 'c) list], using the function [eq]
to equate values of type ['a] and ['b] together
- Raises an exception if there does not exist any element in [xs]
that [eq] deems to be equal to a key in [yzs] *)letmerge_list_with_assoc_list(xs:'alist)(yzs:('b*'c)list)~(eq:'a->'b->bool):('a*'c)list=List.mapyzs~f:(fun(y,z)->matchList.find_opt~f:(funx->eqxy)xswith|Somex'->(x',z)|None->failwith"failed to match an element of ['a] with an element of ['b]")(** Returns true the abstract type declaration in a [signature]
is parameterized (e.g. ['a t]), else returns [false] *)letis_abs_ty_parameterized(sig_items:signature):bool=List.fold_left~f:(funacc{psig_desc;_}->matchpsig_descwith|Psig_type(_rec_flag,ty_decls)->(matchty_declswith|[]->acc|_->list_or@@List.map~f:(fun{ptype_name;ptype_params;_}->String.equalptype_name.txt"t"&¬(list_is_emptyptype_params))ty_decls)|_->acc)~init:falsesig_items