{- |
Copyright : (c) Henning Thielemann 2008-2010
Maintainer : haskell@henning-thielemann.de
Stability : stable
Portability : Haskell 98
This module contains internal functions (*Unsafe)
that I had liked to re-use in the NumericPrelude type hierarchy.
However since the Eq and Ord instance already require the Num class,
we cannot use that in the NumericPrelude.
-}moduleNumeric.NonNegative.ChunkyPrivate(T,fromChunks,fromNumber,toChunks,toNumber,zero,normalize,isNull,isPositive,minMaxDiff,divModStrict,fromChunksUnsafe,toChunksUnsafe,)whereimportqualifiedNumeric.NonNegative.ClassasNonNegimportNumeric.NonNegative.Class((-|),)importControl.Monad(liftM,liftM2)importqualifiedData.MonoidasMnimportTest.QuickCheck(Arbitrary(arbitrary)){- |
A chunky non-negative number is a list of non-negative numbers.
It represents the sum of the list elements.
It is possible to represent a finite number with infinitely many chunks
by using an infinite number of zeros.
Note the following problems:
Addition is commutative only for finite representations.
E.g. @let y = min (1+y) 2 in y@ is defined,
@let y = min (y+1) 2 in y@ is not.
-}newtypeTa=Cons{decons::[a]}fromChunks::NonNeg.Ca=>[a]->TafromChunks=ConsfromNumber::NonNeg.Ca=>a->TafromNumber=fromChunks.(:[]){- |
This routine exposes the inner structure of the lazy number.
-}toChunks::Ta->[a]toChunks=deconstoNumber::NonNeg.Ca=>Ta->atoNumber=sum.deconsinstance(Showa)=>Show(Ta)whereshowsPrecpx=showParen(p>10)(showString"Chunky.fromChunks ".showsPrec10(deconsx))lift2::([a]->[a]->[a])->(Ta->Ta->Ta)lift2f(Consx)(Consy)=Cons$fxyzero::Tazero=Cons[]{- |
Remove zero chunks.
-}normalize::NonNeg.Ca=>Ta->Tanormalize=Cons.filter(>0).deconsisNullList::NonNeg.Ca=>[a]->BoolisNullList=null.filter(>0)isNull::NonNeg.Ca=>Ta->BoolisNull=isNullList.decons-- null . decons . normalizeisPositive::NonNeg.Ca=>Ta->BoolisPositive=not.isNullcheck::String->Bool->a->acheckfuncNamebx=ifbthenxelseerror("Numeric.NonNegative.Chunky."++funcName++": negative number")glue::(NonNeg.Ca)=>[a]->[a]->([a],[a],Bool)glue[]ys=([],ys,True)gluexs[]=([],xs,False)glue(x:xs)(y:ys)=let(z,(zs,rs,b))=casecomparexyofLT->(x,gluexs((y-|x):ys))GT->(y,glue((x-|y):xs)ys)EQ->(x,gluexsys)in(z:zs,rs,b){- |
In @minMaxDiff x y == (z,r,b)@
@z@ represents @min x y@,
@r@ represents @max x y - min x y@,
and @x<y ==> b@ or @x>y ==> not b@,
for @x==y@ the value of b is arbitrary.
-}minMaxDiff::(NonNeg.Ca)=>Ta->Ta->(Ta,Ta,Bool)minMaxDiff(Consxs)(Consys)=let(zs,rs,b)=gluexsysin(Conszs,Consrs,b)equalList::(NonNeg.Ca)=>[a]->[a]->BoolequalListxy=let(_,r,_)=gluexyinisNullListrcompareList::(NonNeg.Ca)=>[a]->[a]->OrderingcompareListxy=let(_,r,b)=gluexyinifisNullListrthenEQelseifbthenLTelseGTminList::(NonNeg.Ca)=>[a]->[a]->[a]minListxy=let(z,_,_)=gluexyinzmaxList::(NonNeg.Ca)=>[a]->[a]->[a]maxListxy=let(z,r,_)=gluexyinz++rinstance(NonNeg.Ca)=>Eq(Ta)where(Consx)==(Consy)=equalListxyinstance(NonNeg.Ca)=>Ord(Ta)wherecompare(Consx)(Consy)=compareListxymin=lift2minListmax=lift2maxListinstance(NonNeg.Ca)=>NonNeg.C(Ta)where(Consx)-|(Consw)=letsub_[]=[]subz(y:ys)=ifz<ythen(y-|z):yselsesub(z-|y)ysinCons(foldrsubxw)instance(NonNeg.Ca)=>Num(Ta)where(+)=Mn.mappend(Consx)-(Consy)=let(_,d,b)=gluexyd'=Consdincheck"-"(notb||isNulld')d'negatex=check"negate"(isNullx)xfromInteger=fromNumber.fromInteger(*)=lift2(liftM2(*))abs=idsignum=fromNumber.(\b->ifbthen1else0).isPositiveinstance(Reala,NonNeg.Ca)=>Real(Ta)wheretoRational=toRational.toNumber{- required for Integral instance -}instance(Enuma,NonNeg.Ca)=>Enum(Ta)wheretoEnum=fromNumber.toEnumfromEnum=fromEnum.toNumberinstance(Integrala,NonNeg.Ca)=>Integral(Ta)wheretoInteger=toInteger.toNumberquot=divrem=modquotRem=divModdivModxy=casedivModStrictx(toNumbery)of(q,r)->(q,fromNumberr)divModStrict::(Integrala,NonNeg.Ca)=>Ta->a->(Ta,a)divModStrictx0y=letrecourse[]r=([],r)recourse(x:xs)r0=let(q1,r1)=divMod(x+r0)y(q2,r2)=recoursexsr1in(q1:q2,r2)(cs,rm)=recourse(toChunksx0)0in(fromChunkscs,rm)instanceMn.Monoid(Ta)wheremempty=zeromappend=lift2(++)instance(NonNeg.Ca,Arbitrarya)=>Arbitrary(Ta)wherearbitrary=liftMConsarbitrary{- * Functions that may break invariants -}fromChunksUnsafe::[a]->TafromChunksUnsafe=Cons{- |
This routine exposes the inner structure of the lazy number
and is actually the same as 'toChunks'.
It was considered dangerous,
but you can observe the lazy structure
in tying-the-knot applications anyway.
So the explicit revelation of the chunks seems not to be worse.
-}toChunksUnsafe::Ta->[a]toChunksUnsafe=decons