{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleInstances #-}
{-# OPTIONS_HADDOCK hide #-}
module Internal.Coin
(
Coin
, coinFromIntegral
, coinFromNatural
, coinToIntegral
, coinToNatural
, pred
, succ
, add
, sub
, mul
, div
, mod
, distance
, isZero
, zero
, one
) where
import Prelude hiding
( div, fromIntegral, mod, pred, succ )
import GHC.Generics
( Generic )
import Numeric.Natural
( Natural )
import Quiet
( Quiet (Quiet) )
import qualified Prelude
newtype Coin = Coin { unCoin :: Natural }
deriving stock (Eq, Generic, Ord)
deriving Show via (Quiet Coin)
coinFromIntegral :: Integral i => i -> Maybe Coin
coinFromIntegral i
| i >= 0 = Just $ Coin $ Prelude.fromIntegral i
| otherwise = Nothing
coinFromNatural :: Natural -> Coin
coinFromNatural = Coin
coinToIntegral :: Integral i => Coin -> i
coinToIntegral (Coin i) = Prelude.fromIntegral i
coinToNatural :: Coin -> Natural
coinToNatural = unCoin
add :: Coin -> Coin -> Coin
add (Coin x) (Coin y) = Coin $ x + y
sub :: Coin -> Coin -> Maybe Coin
sub (Coin x) (Coin y) = coinFromIntegral $ toInteger x - toInteger y
mul :: Integral i => Coin -> i -> Maybe Coin
mul (Coin x) y = coinFromIntegral $ toInteger x * toInteger y
div :: Integral i => Coin -> i -> Maybe Coin
div (Coin x) y
| y <= 0 = Nothing
| otherwise = coinFromIntegral $ toInteger x `Prelude.div` toInteger y
mod :: Integral i => Coin -> i -> Maybe Coin
mod (Coin x) y
| y <= 0 = Nothing
| otherwise = coinFromIntegral $ toInteger x `Prelude.mod` toInteger y
distance :: Coin -> Coin -> Coin
distance (Coin x) (Coin y)
| x >= y = Coin $ x - y
| otherwise = Coin $ y - x
pred :: Coin -> Maybe Coin
pred x = x `sub` one
succ :: Coin -> Coin
succ x = x `add` one
isZero :: Coin -> Bool
isZero = (== zero)
zero :: Coin
zero = Coin 0
one :: Coin
one = Coin 1
newtype Sum a = Sum { getSum :: a }
deriving stock (Eq, Generic, Ord)
deriving Show via (Quiet (Sum a))
instance Monoid Coin where
mempty = zero
instance Semigroup Coin where
(<>) = add