123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163(* 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.voidmoduleNatural:sigtype'atvalorder:'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=T:int->unittletorder(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'aset='aNatural.tmoduletypeSet=Natural.Tvalcardinal:'aset->inttype'aelt=privateintvalelt_of_int:'aset->int->'aeltvalelt_to_int:'aelt->intvaliter_set:'aset->('aelt->unit)->unitvalrev_iter_set:'aset->('aelt->unit)->unitvalall_elements:'aset->'aeltarray(* Temporary API, should be replaced by something array-like in the future *)moduletypeMap=sigtypedomainvaldomain:domainsettypecodomainvalget:domainelt->codomainendtype'amap=(moduleMapwithtypecodomain='a)moduleMap_of_array(A:sigtypecodomainvaltable:codomainarrayend):Mapwithtypecodomain=A.codomainvaliter_map:'amap->('a->unit)->unitend=structtype'aset='aNatural.tmoduletypeSet=Natural.Tletcardinal=Natural.to_inttype'aelt=intletelt_of_int(typea)(set:aset)n:aelt=letc=cardinalsetinifn>=0&&n<cthennelsePrintf.ksprintfinvalid_arg"Strong.Finite.of_int #%d %d: %d is not in [0; %d["cnncletelt_to_intx=xletiter_set(typea)(set:aset)f=fori=0tocardinalset-1dofidoneletrev_iter_set(typea)(set:aset)f=fori=cardinalset-1downto0dofidoneletall_elements(typea)(set:aset)=Array.init(cardinalset)(funx->x)(* Temporary API, should be replaced by something array-like in the future *)moduletypeMap=sigtypedomainvaldomain:domainsettypecodomainvalget:domainelt->codomainendtype'amap=(moduleMapwithtypecodomain='a)moduleMap_of_array(A:sigtypecodomainvaltable:codomainarrayend):Mapwithtypecodomain=A.codomain=structmoduleCard=Natural.Nth(structletn=Array.lengthA.tableend)typedomain=Card.nletdomain=Card.ntypecodomain=A.codomainletgeti=A.table.(i)endletiter_map(typea)((moduleMap):amap)(f:a->unit):unit=iter_setMap.domain(funelt->f(Map.getelt))end