content: module Numeric.Natural
    ( Natural
    , minusNaturalMaybe
    ) where
  import qualified Prelude(); import MiniPrelude
  import Control.Exception
  import Data.Bits.Base
  import Data.Coerce
  import Data.Integer
  import Data.Ix
  import Data.Real
  import Text.Read
  
  newtype Natural = N Integer
    deriving (Eq, Ord, Ix)
  
  instance Show Natural where
    showsPrec p (N i) = showsPrec p i
  
  instance Read Natural where
    readsPrec d = map (\(n, s) -> (fromInteger n, s))
                    . filter ((>= 0) . fst) . readsPrec d
    readListPrec = readListPrecDefault
    readList     = readListDefault
  
  instance Num Natural where
    N x + N y = N (x + y)
    N x - N y | y > x = throw Underflow
              | otherwise = N (x - y)
    N x * N y = N (x * y)
    abs x = x
    signum x = if x > 0 then 1 else 0
    fromInteger x | x < 0 = throw Underflow
                  | otherwise = N x
  
  instance Enum Natural where
    succ n = n + 1
    pred n = n - 1
    toEnum   = fromInteger . toInteger
    fromEnum = fromInteger . toInteger
    enumFrom = coerce (enumFrom @Integer)
    enumFromThen x1 x2
      | x2 >= x1 = coerce (enumFromThen @Integer) x1 x2
      | otherwise = enumFromThenTo x1 x2 0
    enumFromTo = coerce (enumFromTo @Integer)
    enumFromThenTo = coerce (enumFromThenTo @Integer)
  
  instance Integral Natural where
    toInteger (N i) = i
    quotRem (N x) (N y) = (N q, N r) where (q, r) = quotRem x y
  
  instance Real Natural where
    toRational (N i) = toRational i
  
  minusNaturalMaybe :: Natural -> Natural -> Maybe Natural
  minusNaturalMaybe x y | x < y = Nothing
                        | otherwise = Just (x - y)
  
  instance Bits Natural where
    (.&.) = coerce ((.&.) @Integer)
    (.|.) = coerce ((.|.) @Integer)
    xor = coerce (xor @Integer)
    complement _ = error "Bits.complement: Natural complement undefined"
    shift = coerce (shift @Integer)
    rotate = coerce (rotate @Integer)
    zeroBits = coerce (zeroBits @Integer)
    bit = coerce (bit @Integer)
    setBit = coerce (setBit @Integer)
    clearBit = coerce (clearBit @Integer)
    complementBit = coerce (complementBit @Integer)
    testBit = coerce (testBit @Integer)
    shiftL = coerce (shiftL @Integer)
    unsafeShiftL = coerce (unsafeShiftL @Integer)
    shiftR = coerce (shiftR @Integer)
    unsafeShiftR = coerce (unsafeShiftR @Integer)
    rotateL = coerce (rotateL @Integer)
    rotateR = coerce (rotateR @Integer)
    popCount = coerce (popCount @Integer)
    bitSizeMaybe = coerce (bitSizeMaybe @Integer)
    bitSize = coerce (bitSize @Integer)
    isSigned _ = False
  