-- |Provides a type for natural numbers.
module Data.Natural (

    Natural

) where

    -- |The type of natural numbers.
    newtype Natural = Natural Integer deriving (Eq, Ord, Enum)

    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

            -- This is Control.Arrow.first, specialized to (->).
            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 = Natural (integer1 * integer2)

        negate = fromInteger . negate . toInteger

        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)

        toInteger (Natural integer) = integer