123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260(* Type-level equality *)type(_,_)eq=Refl:('a,'a)eqletfollow_eq(typeab)(Refl:(a,b)eq)(x:a):b=x(* Strongly typed ordering *)moduleOrder=structtype(_,_)t=Lt|Eq:('a,'a)t|Gtendtype('a,'b)order=('a,'b)Order.tletorder_from_comparisonn=ifn<0thenOrder.Ltelseifn>0thenOrder.GtelseOrder.Eq(* Uninhabitated type *)typevoid={void:'a.'a}letvoidv=v.voidtype'anatural=T:int->unitnaturalmoduleNatural:sigtype'at='anaturalvalorder:'at->'bt->('a,'b)ordervallift_eq:('a,'b)eq->('at,'bt)eqvalto_int:'at->inttypezerovalzero:zerottypeonevalone:onetmoduletypeT=sigtypenvaln:ntendmoduleNth(N:sigvaln:intend):Tvalnth:int->(moduleT)type('a,'b)sumvaladd:'at->'bt->('a,'b)sumtvalsum_comm:(('a,'b)sum,('b,'a)sum)eqvalsum_assoc:((('a,'b)sum,'c)sum,('a,('b,'c)sum)sum)eqtype('a,'b)prodvalmul:'at->'bt->('a,'b)prodtvalprod_comm:(('a,'b)prod,('b,'a)prod)eqvalprod_assoc:((('a,'b)prod,'c)prod,('a,('b,'c)prod)prod)eqend=structtype'at='anaturalletorder(typeab)(Ta:at)(Tb:bt):(a,b)order=Order.(ifa<bthenLtelseifa>bthenGtelseEq)letlift_eq(typeab)(Refl:(a,b)eq):(at,bt)eq=Reflletto_int(typen)(Tn:nt)=ntypezero=unitletzero:zerot=T0typeone=unitletone:onet=T1moduletypeT=sigtypenvaln:ntendmoduleNth(N:sigvaln:intend):T=structtypen=unitletn:nt=TN.nendletnthn=letmoduleN=structtypen=unitletn=Tnendin(moduleN:T)type('a,'b)sum=unitletadd(typeab)(Ta:at)(Tb:bt):(a,b)sumt=T(a+b)letsum_comm(typeab):((a,b)sum,(b,a)sum)eq=Reflletsum_assoc(typeabc):(((a,b)sum,c)sum,(a,(b,c)sum)sum)eq=Refltype('a,'b)prod=unitletmul(typeab)(Ta:at)(Tb:bt):(a,b)prodt=T(a*b)letprod_comm(typeab):((a,b)prod,(b,a)prod)eq=Reflletprod_assoc(typeabc):(((a,b)prod,c)prod,(a,(b,c)prod)prod)eq=Reflend(* Finite sets: interpret naturals as the cardinality of a set *)moduleFinite:sigtype'nset='nNatural.ttype'nelt=privateintmoduleSet:sigmoduletypeT=Natural.Tvalcardinal:'nset->intvaliter:'nset->('nelt->unit)->unitvalrev_iter:'nset->('nelt->unit)->unitvalfold_left:'nset->('b->'nelt->'b)->'b->'bvalfold_right:'nset->('nelt->'b->'b)->'b->'bmoduleGensym():sigtypenvalfreeze:unit->nsetvalfresh:unit->neltendendmoduleElt:sigvalof_int_opt:'nset->int->'neltoptionvalof_int:'nset->int->'neltvalto_int:'nelt->intvalcompare:'nelt->'nelt->intendmoduleArray:sigtype('n,'a)t=private'aarraytype'a_array=A:('n,'a)t->'a_array[@@ocaml.unboxed]valempty:(Natural.zero,_)tvalis_empty:('n,'a)t->(Natural.zero,'n)eqoptionvallength:('n,'a)t->'nsetexternalget:('n,'a)t->'nelt->'a="%array_unsafe_get"externalset:('n,'a)t->'nelt->'a->unit="%array_unsafe_set"valmake:'nset->'a->('n,'a)tvalinit:'nset->('nelt->'a)->('n,'a)tvalmake_matrix:'iset->'jset->'a->('i,('j,'a)t)tvalappend:('n,'a)t->('m,'a)t->(('n,'m)Natural.sum,'a)tvalof_array:'aarray->'a_arraymoduletypeT=sigincludeNatural.Ttypeavaltable:(n,a)tendmoduleOf_array(A:sigtypeavaltable:aarrayend):Twithtypea=A.avalmodule_of_array:'aarray->(moduleTwithtypea='a)valto_array:(_,'a)t->'aarrayvalall_elements:'nset->('n,'nelt)tvaliter:('a->unit)->(_,'a)t->unitvaliteri:('nelt->'a->unit)->('n,'a)t->unitvalrev_iter:('a->unit)->(_,'a)t->unitvalrev_iteri:('nelt->'a->unit)->('n,'a)t->unitvalmap:('a->'b)->('n,'a)t->('n,'b)tvalmapi:('nelt->'a->'b)->('n,'a)t->('n,'b)tvalfold_left:('a->'b->'a)->'a->('n,'b)t->'avalfold_right:('b->'a->'a)->('n,'b)t->'a->'avaliter2:('a->'b->unit)->('n,'a)t->('n,'b)t->unitvalmap2:('a->'b->'c)->('n,'a)t->('n,'b)t->('n,'c)tvalcopy:('n,'a)t->('n,'a)tendend=structtype'aset='aNatural.ttype'aelt=intmoduleSet=structmoduletypeT=Natural.Tletcardinal=Natural.to_intletiter(typen)(set:nset)f=fori=0tocardinalset-1dofidoneletrev_iter(typen)(set:nset)f=fori=cardinalset-1downto0dofidoneletfold_left(typen)(set:nset)facc=letacc=refaccinfori=0tocardinalset-1doacc:=f!accidone;!accletfold_right(typen)(set:nset)facc=letacc=refaccinfori=cardinalset-1downto0doacc:=fi!accdone;!accmoduleGensym()=structtypen=unitletcounter=ref0letfrozen=reffalseletfreeze()=frozen:=true;T!counterletfresh()=if!frozenthenfailwith"Finite.Set.Gensym.fresh: set has is frozen";letresult=!counterinincrcounter;resultendendmoduleElt=structletof_int_opt(typen)(set:nset)n:neltoption=letc=Set.cardinalsetinifn>=0&&n<cthenSomenelseNoneletof_int(typen)(set:nset)n:nelt=letc=Set.cardinalsetinifn>=0&&n<cthennelsePrintf.ksprintfinvalid_arg"Strong.Finite.Elt.of_int #%d %d: %d is not in [0; %d["cnncletto_intx=xletcompare=Int.compareendmoduleArray=structtype('n,'a)t='aarraytype'a_array=A:('n,'a)t->'a_array[@@ocaml.unboxed]letempty:(Natural.zero,_)t=[||]externalget:('n,'a)t->'nelt->'a="%array_unsafe_get"externalset:('n,'a)t->'nelt->'a->unit="%array_unsafe_set"letlength(a:('n,'a)t):'nset=(Obj.magic(T(Array.lengtha):_natural):_natural)letis_empty=function[||]->Some(Obj.magicRefl)|_->Noneletmakenx=Array.make(Set.cardinaln)xletinitnf=Array.init(Set.cardinaln)fletmake_matrixisjsv=Array.make_matrix(Set.cardinalis)(Set.cardinaljs)vletappend=Array.appendletof_arrayarr=AarrmoduletypeT=sigincludeNatural.Ttypeavaltable:(n,a)tendmoduleOf_array(A:sigtypeavaltable:aarrayend):Twithtypea=A.a=structincludeNatural.Nth(structletn=Array.lengthA.tableend)typea=A.alettable=A.tableendletmodule_of_array(typea)(arr:aarray):(moduleTwithtypea=a)=let(moduleNth)=Natural.nth(Array.lengtharr)in(modulestructincludeNthtypenonreca=alettable=arrend)letto_arrayx=xletall_elements(typea)(set:aset)=Array.init(Set.cardinalset)(funx->x)letiter=Array.iterletiteri=Array.iteriletrev_iterft=fori=Array.lengtht-1downto0dof(getti)doneletrev_iterift=fori=Array.lengtht-1downto0dofi(getti)doneletmap=Array.mapletmapi=Array.mapiletfold_left=Array.fold_leftletfold_right=Array.fold_rightletiter2=Array.iter2letmap2=Array.map2letcopy=Array.copyendend