module Data.Natural (
Natural,
monus,
View (Zero, Succ),
view,
fold
) where
import Data.Monoid
uncheckedPred :: Natural -> Natural
uncheckedPred (Natural integer) = Natural (pred integer)
newtype Natural = Natural Integer deriving (Eq, Ord)
instance Enum Natural where
succ (Natural integer) = Natural (succ integer)
pred = fromInteger . pred . toInteger
toEnum = fromInteger . toEnum
fromEnum = fromEnum . toInteger
enumFrom (Natural start) = map Natural (enumFrom start)
enumFromThen (Natural start) (Natural next) = map Natural $
if start > next
then enumFromThenTo start next 0
else enumFromThen start next
enumFromTo (Natural start) (Natural end) = map Natural (enumFromTo start end)
enumFromThenTo (Natural start) (Natural next) (Natural end) = map Natural $
enumFromThenTo start next end
instance Show Natural where
showsPrec prec (Natural integer) = showsPrec prec integer
instance Read Natural where
readsPrec prec str = map (first fromInteger) (readsPrec prec str) where
first :: (val -> val') -> (val,other) -> (val',other)
first fun (val,other) = (fun val,other)
instance Num Natural where
Natural integer1 + Natural integer2 = Natural (integer1 + integer2)
Natural integer1 Natural integer2 = fromInteger (integer1 integer2)
Natural integer1 * Natural integer2 = Natural (integer1 * integer2)
abs = id
signum (Natural integer) = Natural (signum integer)
fromInteger integer | integer >= 0 = Natural integer
| otherwise = error "Data.Natural: natural cannot be negative"
instance Real Natural where
toRational = toRational . toInteger
instance Integral Natural where
quotRem (Natural integer1) (Natural integer2) = let
(quot,rem) = quotRem integer1 integer2
in (Natural quot,Natural rem)
divMod = quotRem
toInteger (Natural integer) = integer
monus :: Natural -> Natural -> Natural
monus (Natural integer1) (Natural integer2) | integer1 > integer2 = Natural (integer1 integer2)
| otherwise = Natural 0
data View = Zero | Succ Natural
view :: Natural -> View
view (Natural 0) = Zero
view (Natural integer) = Succ (Natural (pred integer))
fold :: accu -> (accu -> accu) -> Natural -> accu
fold zeroAccu _ (Natural 0) = zeroAccu
fold zeroAccu succAccu (Natural integer) = succAccu $
fold zeroAccu succAccu (Natural (pred integer))