{- |
Encoding of ordinals up to epsilon_0 as an iterated multiset:
definition in Basic Proof Theory by Troelstra and Schwichenberg.
Note, this is not the most efficient way to calculate ordinals.
This library is better than having none.
I think CNF representation would be more efficent,
planning to add in the next version of this library.
For further analysis on efficiency of implementations on ordinals see
<http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.91.8089>
FYI, an ordinal calculator that covers wider range beyond epsion_0
can be found at <http://www.mtnmath.com/ord/> which is written C++.
However, I found a serious error in this calculator (ver 0.2):
the property a^b * a^c == a^(b+c) does not hold. For example,
@
ordCalc> 3 ^(w^w + w + 1) * 3^(w^w) == 3 ^ (w^w + w + 1 + w^w)
FALSE
@
This calculator didn't seem to run QuickCeck style automatic
testing, although it does have hundreds (or maybe more than a thousand)
tests cases but some of them even causes segmentation faults
depending on the machine I built this ordCalc.
-}moduleMath.Ordinals.MultiSet(-- * TypesOrdinal(..)-- * Operators,(^:)-- | There are more operators such as-- '+' (addition), '*' (multiplication), '-', (left addtion)-- defined in the 'Num' class instance declaration for 'Ordinal'.-- Although ordinals are not really 'Num' we decided to make it-- as a 'Num' instance for convenience; We can use functions such-- as 'sum' and 'product' over list of ordinals and they behave well.-- We also plan to implement division and remainder operations-- in the 'Integral' class instance for similar reason. For further-- information on class instances see the source code.-- * Auxiliary functions,w,wf-- * Auxiliary operators-- | These operators can manipulate the 'Ordinal' newtype data structure-- internally. Use with care since it can break the well-formedness ('wf')-- of ordinal representation.,(.:),(++.),(.++.))whereimportData.List(groupBy,intersperse)newtypeOrdinal=O[Ordinal]derivingEq-- | convenience function that takes an argument as the power of omega-- (the first limit ordinal).w::Ordinal->Ordinalwo=O[o]instanceShowOrdinalwhereshowo@(Oos)|o<O[1]=show(lengthos)|otherwise="("++(concat.intersperse" + ")["w "++showo'++showFactor(lengthos')|os'@(o':_)<-oss]++")"whereshowFactork=ifk==1then""else(" *"++showk)oss=groupBy(==)osinstanceOrdOrdinalwherecompare00=EQcompare0_=LTcompare_0=GTcompare(O(a:as))(O(b:bs))=casecompareabofEQ->compareasbsr->r-- | well formedness of ordinalswf::Ordinal->Boolwf(O[])=Truewf(O[o])=wfowf(O(o:os@(o':_)))=o>=o'&&wf(Oos)instanceEnumOrdinalwhere-- TODOtoEnum=fromIntfromEnum=toIntinstanceRealOrdinalwhere-- TODOinstanceIntegralOrdinalwhere-- works only within Int limittoIntegero@(Oas)|all(0==)as=fromIntegral(toInto)toInteger_=error"ordinal not less than omega"-- | Left division. not yet defineddivab=fst(divModab)-- | not yet definedmodab=snd(divModab)-- | not yet defineddivMod=quotRem-- | not yet defined -- TODO -- somebody help figure this outquotRem__=error"Ordinal quotRem not yet defined"instanceNumOrdinalwhere-- to parse in haskell integer literals within Int limitfromIntegerk=fromInt(fromIntegralk)abs=idsignum0=0signum(O(o:os))=O[o]-- | Addition.o+0=oOas+Obs@(b:_)=O(takeWhile(>=b)as++bs)-- | Left subtraction-- for a <= b exists r = b - a such that a + r = b-- i.e., a + (b - a) = b for a <= bo-0=o0-_=0o1@(O(a:as))-o2@(O(b:bs))=casecompareabofLT->0EQ->Oas-ObsGT->o1-- | Multiplication.-- Implemented as something similar to-- <http://www.volny.cz/behounek/logic/papers/ordcalc/index.html>0*_=0o1@(O(a:as))*Obs|nullbs'=sum[o1|_<-zs]-- finite|nullzs=O[a+b|b<-bs']-- limit ordinal|otherwise=o1*Obs'+o1*Ozs-- non-limit ordinalwhere(bs',zs)=span(>0)bs(as1,as2)=span(a==)(a:as)-- | Exponentiation.-- Defined a new operator since neither '^' nor '^^' will work.-- Note, @(w o)@ is same as @(w 1 :^ o)@ for any oridnal @o@.infixr8^:(^:)::Ordinal->Ordinal->Ordinal_^:0=10^:_=01^:_=1o1@(OosA@(a:_))^:o2@(OosB@(b:_))|finiteB=o1^:(o2-1)*o1-- finite power|mB>0=o1^:OosB'*o1^:mB-- non-limit ordinals|finiteA=O[o2]|otherwise=O[a*o2]where(osA',zsA)=span(>0)osA(osB',zsB)=span(>0)osBmA=OzsAmB=OzsBfiniteB=nullosB'finiteA=nullosA'toInt(Oas)|all(0==)as=lengthastoInt_=error"ordinal not less than omega"fromIntk=O(replicatek(O[]))infixr5.:o.:Oos=O(o:os)infixr5++.as++.Obs=O(as++bs)infixr5.++.Oas.++.Obs=O(as++bs)