123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Maps with Heterogeneous Values} *)(*$R
let module M = CCMixmap.Make(CCInt) in
let inj_int = CCMixmap.create_inj() in
let inj_str = CCMixmap.create_inj() in
let inj_list_int = CCMixmap.create_inj() in
let m =
M.empty
|> M.add ~inj:inj_int 1 1
|> M.add ~inj:inj_str 2 "2"
|> M.add ~inj:inj_list_int 3 [3;3;3]
in
assert_equal (M.get ~inj:inj_int 1 m) (Some 1) ;
assert_equal (M.get ~inj:inj_str 1 m) None ;
assert_equal (M.get ~inj:inj_str 2 m) (Some "2") ;
assert_equal (M.get ~inj:inj_int 2 m) None ;
assert_equal (M.get ~inj:inj_list_int 3 m) (Some [3;3;3]) ;
assert_equal (M.get ~inj:inj_str 3 m) None ;
*)type'binjection={get:(unit->unit)->'boption;set:'b->(unit->unit);}letcreate_inj()=letr=refNoneinletgetf=r:=None;f();!randsetv=(fun()->r:=Somev)in{get;set}moduletypeS=sigtypekeytypet(** A map containing values of different types, indexed by {!key}. *)valempty:t(** Empty map *)valget:inj:'ainjection->key->t->'aoption(** Get the value corresponding to this key, if it exists and
belongs to the same key *)valadd:inj:'ainjection->key->'a->t->t(** Bind the key to the value, using [inj] *)valfind:inj:'ainjection->key->t->'a(** Find the value for the given key, which must be of the right type.
@raise Not_found if either the key is not found, or if its value
doesn't belong to the right type *)valcardinal:t->int(** Number of bindings *)valremove:key->t->t(** Remove the binding for this key *)valmem:inj:_injection->key->t->bool(** Is the given key in the map, with the right type? *)valiter_keys:f:(key->unit)->t->unit(** Iterate on the keys of this map *)valfold_keys:f:('a->key->'a)->x:'a->t->'a(** Fold over the keys *)(** {2 Iterators} *)type'asequence=('a->unit)->unitvalkeys_seq:t->keysequence(** All the keys *)valbindings_of:inj:'ainjection->t->(key*'a)sequence(** All the bindings that come from the corresponding injection *)typevalue=|Value:('ainjection->'aoption)->valuevalbindings:t->(key*value)sequence(** Iterate on all bindings *)endmoduletypeORD=sigtypetvalcompare:t->t->intendmoduleMake(X:ORD):Swithtypekey=X.t=structmoduleM=Map.Make(X)typekey=X.ttypet=(unit->unit)M.tletempty=M.emptyletfind~injxmap=matchinj.get(M.findxmap)with|None->raiseNot_found|Somev->vletget~injxmap=tryinj.get(M.findxmap)withNot_found->Noneletadd~injxymap=M.addx(inj.sety)mapletcardinal=M.cardinalletremove=M.removeletis_some=function|None->false|Some_->trueletmem~injxmap=tryis_some(inj.get(M.findxmap))withNot_found->falseletiter_keys~fmap=M.iter(funx_->fx)mapletfold_keys~f~xmap=M.fold(funx_acc->faccx)mapx(** {2 Iterators} *)type'asequence=('a->unit)->unitletkeys_seqmapyield=M.iter(funx_->yieldx)mapletbindings_of~injmapyield=M.iter(funkvalue->matchinj.getvaluewith|None->()|Somev->yield(k,v))maptypevalue=|Value:('binjection->'boption)->valueletbindingsmapyield=M.iter(funxy->yield(x,Value(funinj->inj.gety)))mapend