123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249(*This functor generates a module, not a class, and has no mutable member, more closely
resembling the Map interface*)moduleBimap_single(ModuleA:Core.Comparable.S)(ModuleB:Core.Comparable.S)=struct(*better than passing tuples around and possibly getting order
backwards somewhere, after which all bets are off; so we saddle
client code writers with this type*)typet={fwdmap:ModuleB.Map.Key.tModuleA.Map.t;revmap:ModuleA.Map.Key.tModuleB.Map.t}letmake_t~fwd_map~rev_map={fwdmap=fwd_map;revmap=rev_map}(* let empty_forward_map () = ModuleA.Map.empty
let empty_reverse_map () = ModuleB.Map.empty*)letget_rev_mapt=t.revmapletget_fwd_mapt=t.fwdmapletsett~key~data=ifModuleA.Map.memt.fwdmapkeythenletvalue=ModuleA.Map.find_exnt.fwdmapkeyinletnewfmap=ModuleA.Map.sett.fwdmap~key~datainletnewrmap=ModuleB.Map.removet.revmapvalueinletnewrmap=ModuleB.Map.setnewrmap~key:data~data:keyin{fwdmap=newfmap;revmap=newrmap}elseletnewfmap=ModuleA.Map.sett.fwdmap~key~datainletnewrmap=ModuleB.Map.sett.revmap~key:data~data:keyin{fwdmap=newfmap;revmap=newrmap}letset_reverset~key~data=ifModuleB.Map.memt.revmapkeythenletvalue=ModuleB.Map.find_exnt.revmapkeyinletnewrmap=ModuleB.Map.sett.revmap~key~datainletnewfmap=ModuleA.Map.removet.fwdmapvalueinletnewfmap=ModuleA.Map.setnewfmap~key:data~data:keyin{fwdmap=newfmap;revmap=newrmap}elseletnewrmap=ModuleB.Map.sett.revmap~key~datainletnewfmap=ModuleA.Map.sett.fwdmap~key:data~data:keyin{fwdmap=newfmap;revmap=newrmap}letchanget~key~f=letold_value=ModuleA.Map.find_exnt.fwdmapkeyinletnewfmap=ModuleA.Map.changet.fwdmapkey~finletnew_value=ModuleA.Map.find_exnnewfmapkeyinletnewrmap=ModuleB.Map.removet.revmapold_valueinletnewrmap=ModuleB.Map.setnewrmap~key:new_value~data:keyin{fwdmap=newfmap;revmap=newrmap}letchange_reverset~key~f=letold_key=ModuleB.Map.find_exnt.revmapkeyinletnewrmap=ModuleB.Map.changet.revmapkey~finletnew_value=ModuleB.Map.find_exnnewrmapkeyinletnewfmap=ModuleA.Map.removet.fwdmapold_keyinletnewfmap=ModuleA.Map.setnewfmap~key:new_value~data:keyin{fwdmap=newfmap;revmap=newrmap}letcreate_reverse_map_from_forward_map~forward_map=letnewrmap=ModuleB.Map.emptyinletnewrmapref=refnewrmapin(*iteri fits the bill better than iter keys*)let()=ModuleA.Map.iteri~f:(fun~key~data->newrmapref:=(ModuleB.Map.set!newrmapref~key:data~data:key))forward_mapin!newrmaprefletcreate_forward_map_from_reverse_map~reverse_map=letnewfmap=ModuleA.Map.emptyinletnewfmapref=refnewfmapinlet()=ModuleB.Map.iteri~f:(fun~key~data->newfmapref:=ModuleA.Map.set!newfmapref~key:data~data:key)reverse_mapin!newfmaprefletcountt~f=ModuleA.Map.countt.fwdmap~fletcount_reverset~f=ModuleB.Map.countt.revmap~fletcountit~f=ModuleA.Map.countit.fwdmap~fletdatat=ModuleA.Map.datat.fwdmapletdata_reverset=ModuleB.Map.datat.revmapletempty={fwdmap=ModuleA.Map.empty;revmap=ModuleB.Map.empty}letexistst~f=ModuleA.Map.existst.fwdmap~fletexists_reverset~f=ModuleB.Map.existst.revmap~fletexistsit~f=ModuleA.Map.existsit.fwdmap~fletexistsi_reverset~f=ModuleB.Map.existsit.revmap~fletfindt~key=ModuleA.Map.findt.fwdmapkeyletfind_reverset~key=ModuleB.Map.findt.revmapkeyletfind_exnt~key=ModuleA.Map.find_exnt.fwdmapkeyletfind_exn_reverset~key=ModuleB.Map.find_exnt.revmapkeyletfiltert~f=letnew_forward_map=(ModuleA.Map.filtert.fwdmap~f)inletnew_reverse_map=(ModuleB.Map.filter_keyst.revmap~f)in{fwdmap=new_forward_map;revmap=new_reverse_map}letfilter_reverset~f=letnew_reverse_map=(ModuleB.Map.filtert.revmap~f)inletnew_forward_map=(ModuleA.Map.filter_keyst.fwdmap~f)in{fwdmap=new_forward_map;revmap=new_reverse_map}letfilter_keyst~f=letnew_forward_map=(ModuleA.Map.filter_keyst.fwdmap~f)inletnew_reverse_map=(ModuleB.Map.filtert.revmap~f)in{fwdmap=new_forward_map;revmap=new_reverse_map}letfilter_keys_reverset~f=letnew_reverse_map=(ModuleB.Map.filter_keyst.revmap~f)inletnew_forward_map=(ModuleA.Map.filtert.fwdmap~f)in{fwdmap=new_forward_map;revmap=new_reverse_map}letfilterit~f=letnew_forward_map=(ModuleA.Map.filterit.fwdmap~f)inletnew_reverse_map=create_reverse_map_from_forward_map~forward_map:new_forward_mapin{fwdmap=new_forward_map;revmap=new_reverse_map}letfilteri_reverset~f=letnew_reverse_map=(ModuleB.Map.filterit.revmap~f)inletnew_forward_map=create_forward_map_from_reverse_map~reverse_map:new_reverse_mapin{fwdmap=new_forward_map;revmap=new_reverse_map}letfilter_mapt~f=letnew_forward_map=(ModuleA.Map.filter_mapt.fwdmap~f)inletnew_reverse_map=create_reverse_map_from_forward_map~forward_map:new_forward_mapin{fwdmap=new_forward_map;revmap=new_reverse_map}letfilter_map_reverset~f=letnew_reverse_map=(ModuleB.Map.filter_mapt.revmap~f)inletnew_forward_map=create_forward_map_from_reverse_map~reverse_map:new_reverse_mapin{fwdmap=new_forward_map;revmap=new_reverse_map}letfoldt~init~f=ModuleA.Map.foldt.fwdmap~init~fletfold_reverset~init~f=ModuleB.Map.foldt.revmap~init~fletfold_range_inclusivet~min~max~init~f=ModuleA.Map.fold_range_inclusivet.fwdmap~min~max~init~fletfold_rightt~init~f=ModuleA.Map.fold_rightt.fwdmap~init~fletfold_right_reverset~init~f=ModuleB.Map.fold_rightt.revmap~init~fletfor_allt~f=ModuleA.Map.for_allt.fwdmap~fletfor_all_reverset~f=ModuleB.Map.for_allt.revmap~fletis_emptyt=ModuleA.Map.is_emptyt.fwdmapletiter_keyst~f=ModuleA.Map.iter_keyst.fwdmap~fletiter_keys_reverset~f=ModuleB.Map.iter_keyst.revmap~fletitert~f=ModuleA.Map.itert.fwdmap~fletiter_reverset~f=ModuleB.Map.itert.revmap~fletiterit~f=ModuleA.Map.iterit.fwdmap~fletiteri_reverset~f=ModuleB.Map.iterit.revmap~fletkeyst=ModuleA.Map.keyst.fwdmapletkeys_reverset=ModuleB.Map.keyst.revmapletlengtht=ModuleA.Map.lengtht.fwdmapletmapt~f=letnew_forward_map=(ModuleA.Map.mapt.fwdmap~f)inletnew_rev_map=refModuleB.Map.emptyinlet()=ModuleA.Map.iter_keysnew_forward_map~f:(funk->new_rev_map:=ModuleB.Map.set!new_rev_map~key:(ModuleA.Map.find_exnnew_forward_mapk)~data:k)in{fwdmap=new_forward_map;revmap=!new_rev_map}letmap_reverset~f=letnew_reverse_map=(ModuleB.Map.mapt.revmap~f)inletnew_fwd_map=refModuleA.Map.emptyinlet()=ModuleB.Map.iter_keysnew_reverse_map~f:(funk->new_fwd_map:=ModuleA.Map.set!new_fwd_map~key:(ModuleB.Map.find_exnnew_reverse_mapk)~data:k)in{fwdmap=!new_fwd_map;revmap=new_reverse_map}letmapit~f=letnew_forward_map=(ModuleA.Map.mapit.fwdmap~f)inletnew_rev_map=refModuleB.Map.emptyinlet()=ModuleA.Map.iter_keysnew_forward_map~f:(funk->new_rev_map:=ModuleB.Map.set!new_rev_map~key:(ModuleA.Map.find_exnnew_forward_mapk)~data:k)in{fwdmap=new_forward_map;revmap=!new_rev_map}letmapi_reverset~f=letnew_reverse_map=(ModuleB.Map.mapit.revmap~f)inletnew_fwd_map=refModuleA.Map.emptyinlet()=ModuleB.Map.iter_keysnew_reverse_map~f:(funk->new_fwd_map:=ModuleA.Map.set!new_fwd_map~key:(ModuleB.Map.find_exnnew_reverse_mapk)~data:k)in{fwdmap=!new_fwd_map;revmap=new_reverse_map}letmemt~key=ModuleA.Map.memt.fwdmapkeyletmem_reverset~key=ModuleB.Map.memt.revmapkeyletmin_eltt=ModuleA.Map.min_eltt.fwdmapletmin_elt_exnt=ModuleA.Map.min_elt_exnt.fwdmapletmin_elt_reverset=ModuleB.Map.min_eltt.revmapletmin_elt_exn_reverset=ModuleB.Map.min_elt_exnt.revmapletmax_eltt=ModuleA.Map.max_eltt.fwdmapletmax_elt_exnt=ModuleA.Map.max_elt_exnt.fwdmapletmax_elt_reverset=ModuleB.Map.max_eltt.revmapletmax_elt_exn_reverset=ModuleB.Map.max_elt_exnt.revmapletntht~int=ModuleA.Map.ntht.fwdmapintletnth_reverset~int=ModuleB.Map.ntht.revmapintletremovet~key=letreverse_key=ModuleA.Map.find_exnt.fwdmapkeyinletnew_forward_map=ModuleA.Map.removet.fwdmapkeyinletnew_reverse_map=ModuleB.Map.removet.revmapreverse_keyin{fwdmap=new_forward_map;revmap=new_reverse_map}letremove_reverset~key=letfwd_key=ModuleB.Map.find_exnt.revmapkeyinletnew_reverse_map=ModuleB.Map.removet.revmapkeyinletnew_forward_map=ModuleA.Map.removet.fwdmapfwd_keyin{fwdmap=new_forward_map;revmap=new_reverse_map}(* let reverse_map = !reverse_map*)letto_alist?key_ordert=matchCore.Option.is_somekey_orderwith|false->ModuleA.Map.to_alistt.fwdmap|true->ModuleA.Map.to_alist~key_order:(Core.Option.value_exnkey_order)t.fwdmapletupdatet~key~f=letoldvalue=ModuleA.Map.find_exnt.fwdmapkeyinletnew_forward_map=ModuleA.Map.updatet.fwdmapkey~finletnewvalue=ModuleA.Map.find_exnnew_forward_mapkeyinletnew_reverse_map=ModuleB.Map.removet.revmapoldvalueinletnew_reverse_map=ModuleB.Map.setnew_reverse_map~key:newvalue~data:keyin{fwdmap=new_forward_map;revmap=new_reverse_map}end