{-# 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 { Coin -> Natural
unCoin :: Natural }
deriving stock (Coin -> Coin -> Bool
(Coin -> Coin -> Bool) -> (Coin -> Coin -> Bool) -> Eq Coin
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Coin -> Coin -> Bool
== :: Coin -> Coin -> Bool
$c/= :: Coin -> Coin -> Bool
/= :: Coin -> Coin -> Bool
Eq, (forall x. Coin -> Rep Coin x)
-> (forall x. Rep Coin x -> Coin) -> Generic Coin
forall x. Rep Coin x -> Coin
forall x. Coin -> Rep Coin x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Coin -> Rep Coin x
from :: forall x. Coin -> Rep Coin x
$cto :: forall x. Rep Coin x -> Coin
to :: forall x. Rep Coin x -> Coin
Generic, Eq Coin
Eq Coin =>
(Coin -> Coin -> Ordering)
-> (Coin -> Coin -> Bool)
-> (Coin -> Coin -> Bool)
-> (Coin -> Coin -> Bool)
-> (Coin -> Coin -> Bool)
-> (Coin -> Coin -> Coin)
-> (Coin -> Coin -> Coin)
-> Ord Coin
Coin -> Coin -> Bool
Coin -> Coin -> Ordering
Coin -> Coin -> Coin
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Coin -> Coin -> Ordering
compare :: Coin -> Coin -> Ordering
$c< :: Coin -> Coin -> Bool
< :: Coin -> Coin -> Bool
$c<= :: Coin -> Coin -> Bool
<= :: Coin -> Coin -> Bool
$c> :: Coin -> Coin -> Bool
> :: Coin -> Coin -> Bool
$c>= :: Coin -> Coin -> Bool
>= :: Coin -> Coin -> Bool
$cmax :: Coin -> Coin -> Coin
max :: Coin -> Coin -> Coin
$cmin :: Coin -> Coin -> Coin
min :: Coin -> Coin -> Coin
Ord)
deriving Int -> Coin -> ShowS
[Coin] -> ShowS
Coin -> String
(Int -> Coin -> ShowS)
-> (Coin -> String) -> ([Coin] -> ShowS) -> Show Coin
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Coin -> ShowS
showsPrec :: Int -> Coin -> ShowS
$cshow :: Coin -> String
show :: Coin -> String
$cshowList :: [Coin] -> ShowS
showList :: [Coin] -> ShowS
Show via (Quiet Coin)
coinFromIntegral :: Integral i => i -> Maybe Coin
coinFromIntegral :: forall i. Integral i => i -> Maybe Coin
coinFromIntegral i
i
| i
i i -> i -> Bool
forall a. Ord a => a -> a -> Bool
>= i
0 = Coin -> Maybe Coin
forall a. a -> Maybe a
Just (Coin -> Maybe Coin) -> Coin -> Maybe Coin
forall a b. (a -> b) -> a -> b
$ Natural -> Coin
Coin (Natural -> Coin) -> Natural -> Coin
forall a b. (a -> b) -> a -> b
$ i -> Natural
forall a b. (Integral a, Num b) => a -> b
Prelude.fromIntegral i
i
| Bool
otherwise = Maybe Coin
forall a. Maybe a
Nothing
coinFromNatural :: Natural -> Coin
coinFromNatural :: Natural -> Coin
coinFromNatural = Natural -> Coin
Coin
coinToIntegral :: Integral i => Coin -> i
coinToIntegral :: forall i. Integral i => Coin -> i
coinToIntegral (Coin Natural
i) = Natural -> i
forall a b. (Integral a, Num b) => a -> b
Prelude.fromIntegral Natural
i
coinToNatural :: Coin -> Natural
coinToNatural :: Coin -> Natural
coinToNatural = Coin -> Natural
unCoin
add :: Coin -> Coin -> Coin
add :: Coin -> Coin -> Coin
add (Coin Natural
x) (Coin Natural
y) = Natural -> Coin
Coin (Natural -> Coin) -> Natural -> Coin
forall a b. (a -> b) -> a -> b
$ Natural
x Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
y
sub :: Coin -> Coin -> Maybe Coin
sub :: Coin -> Coin -> Maybe Coin
sub (Coin Natural
x) (Coin Natural
y) = Integer -> Maybe Coin
forall i. Integral i => i -> Maybe Coin
coinFromIntegral (Integer -> Maybe Coin) -> Integer -> Maybe Coin
forall a b. (a -> b) -> a -> b
$ Natural -> Integer
forall a. Integral a => a -> Integer
toInteger Natural
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Natural -> Integer
forall a. Integral a => a -> Integer
toInteger Natural
y
mul :: Integral i => Coin -> i -> Maybe Coin
mul :: forall i. Integral i => Coin -> i -> Maybe Coin
mul (Coin Natural
x) i
y = Integer -> Maybe Coin
forall i. Integral i => i -> Maybe Coin
coinFromIntegral (Integer -> Maybe Coin) -> Integer -> Maybe Coin
forall a b. (a -> b) -> a -> b
$ Natural -> Integer
forall a. Integral a => a -> Integer
toInteger Natural
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* i -> Integer
forall a. Integral a => a -> Integer
toInteger i
y
div :: Integral i => Coin -> i -> Maybe Coin
div :: forall i. Integral i => Coin -> i -> Maybe Coin
div (Coin Natural
x) i
y
| i
y i -> i -> Bool
forall a. Ord a => a -> a -> Bool
<= i
0 = Maybe Coin
forall a. Maybe a
Nothing
| Bool
otherwise = Integer -> Maybe Coin
forall i. Integral i => i -> Maybe Coin
coinFromIntegral (Integer -> Maybe Coin) -> Integer -> Maybe Coin
forall a b. (a -> b) -> a -> b
$ Natural -> Integer
forall a. Integral a => a -> Integer
toInteger Natural
x Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`Prelude.div` i -> Integer
forall a. Integral a => a -> Integer
toInteger i
y
mod :: Integral i => Coin -> i -> Maybe Coin
mod :: forall i. Integral i => Coin -> i -> Maybe Coin
mod (Coin Natural
x) i
y
| i
y i -> i -> Bool
forall a. Ord a => a -> a -> Bool
<= i
0 = Maybe Coin
forall a. Maybe a
Nothing
| Bool
otherwise = Integer -> Maybe Coin
forall i. Integral i => i -> Maybe Coin
coinFromIntegral (Integer -> Maybe Coin) -> Integer -> Maybe Coin
forall a b. (a -> b) -> a -> b
$ Natural -> Integer
forall a. Integral a => a -> Integer
toInteger Natural
x Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`Prelude.mod` i -> Integer
forall a. Integral a => a -> Integer
toInteger i
y
distance :: Coin -> Coin -> Coin
distance :: Coin -> Coin -> Coin
distance (Coin Natural
x) (Coin Natural
y)
| Natural
x Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
>= Natural
y = Natural -> Coin
Coin (Natural -> Coin) -> Natural -> Coin
forall a b. (a -> b) -> a -> b
$ Natural
x Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
- Natural
y
| Bool
otherwise = Natural -> Coin
Coin (Natural -> Coin) -> Natural -> Coin
forall a b. (a -> b) -> a -> b
$ Natural
y Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
- Natural
x
pred :: Coin -> Maybe Coin
pred :: Coin -> Maybe Coin
pred Coin
x = Coin
x Coin -> Coin -> Maybe Coin
`sub` Coin
one
succ :: Coin -> Coin
succ :: Coin -> Coin
succ Coin
x = Coin
x Coin -> Coin -> Coin
`add` Coin
one
isZero :: Coin -> Bool
isZero :: Coin -> Bool
isZero = (Coin -> Coin -> Bool
forall a. Eq a => a -> a -> Bool
== Coin
zero)
zero :: Coin
zero :: Coin
zero = Natural -> Coin
Coin Natural
0
one :: Coin
one :: Coin
one = Natural -> Coin
Coin Natural
1
newtype Sum a = Sum { forall a. Sum a -> a
getSum :: a }
deriving stock (Sum a -> Sum a -> Bool
(Sum a -> Sum a -> Bool) -> (Sum a -> Sum a -> Bool) -> Eq (Sum a)
forall a. Eq a => Sum a -> Sum a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Sum a -> Sum a -> Bool
== :: Sum a -> Sum a -> Bool
$c/= :: forall a. Eq a => Sum a -> Sum a -> Bool
/= :: Sum a -> Sum a -> Bool
Eq, (forall x. Sum a -> Rep (Sum a) x)
-> (forall x. Rep (Sum a) x -> Sum a) -> Generic (Sum a)
forall x. Rep (Sum a) x -> Sum a
forall x. Sum a -> Rep (Sum a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Sum a) x -> Sum a
forall a x. Sum a -> Rep (Sum a) x
$cfrom :: forall a x. Sum a -> Rep (Sum a) x
from :: forall x. Sum a -> Rep (Sum a) x
$cto :: forall a x. Rep (Sum a) x -> Sum a
to :: forall x. Rep (Sum a) x -> Sum a
Generic, Eq (Sum a)
Eq (Sum a) =>
(Sum a -> Sum a -> Ordering)
-> (Sum a -> Sum a -> Bool)
-> (Sum a -> Sum a -> Bool)
-> (Sum a -> Sum a -> Bool)
-> (Sum a -> Sum a -> Bool)
-> (Sum a -> Sum a -> Sum a)
-> (Sum a -> Sum a -> Sum a)
-> Ord (Sum a)
Sum a -> Sum a -> Bool
Sum a -> Sum a -> Ordering
Sum a -> Sum a -> Sum a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Sum a)
forall a. Ord a => Sum a -> Sum a -> Bool
forall a. Ord a => Sum a -> Sum a -> Ordering
forall a. Ord a => Sum a -> Sum a -> Sum a
$ccompare :: forall a. Ord a => Sum a -> Sum a -> Ordering
compare :: Sum a -> Sum a -> Ordering
$c< :: forall a. Ord a => Sum a -> Sum a -> Bool
< :: Sum a -> Sum a -> Bool
$c<= :: forall a. Ord a => Sum a -> Sum a -> Bool
<= :: Sum a -> Sum a -> Bool
$c> :: forall a. Ord a => Sum a -> Sum a -> Bool
> :: Sum a -> Sum a -> Bool
$c>= :: forall a. Ord a => Sum a -> Sum a -> Bool
>= :: Sum a -> Sum a -> Bool
$cmax :: forall a. Ord a => Sum a -> Sum a -> Sum a
max :: Sum a -> Sum a -> Sum a
$cmin :: forall a. Ord a => Sum a -> Sum a -> Sum a
min :: Sum a -> Sum a -> Sum a
Ord)
deriving Int -> Sum a -> ShowS
[Sum a] -> ShowS
Sum a -> String
(Int -> Sum a -> ShowS)
-> (Sum a -> String) -> ([Sum a] -> ShowS) -> Show (Sum a)
forall a. Show a => Int -> Sum a -> ShowS
forall a. Show a => [Sum a] -> ShowS
forall a. Show a => Sum a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Sum a -> ShowS
showsPrec :: Int -> Sum a -> ShowS
$cshow :: forall a. Show a => Sum a -> String
show :: Sum a -> String
$cshowList :: forall a. Show a => [Sum a] -> ShowS
showList :: [Sum a] -> ShowS
Show via (Quiet (Sum a))
instance Monoid Coin where
mempty :: Coin
mempty = Coin
zero
instance Semigroup Coin where
<> :: Coin -> Coin -> Coin
(<>) = Coin -> Coin -> Coin
add