{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Taiwan.ID.Digit
( Digit (..)
, fromChar
, toChar
, generate
, FromChar
, FromNat
, ToNat
) where
import Control.Monad.Random
( MonadRandom )
import Data.Finitary
( Finitary )
import GHC.Generics
( Generic )
import GHC.TypeNats
( Nat )
import Taiwan.ID.Utilities
( maybeFinitary, randomFinitary )
import Text.Read
( Read (readPrec), readMaybe )
import Prelude hiding
( fromIntegral )
import qualified Prelude
data Digit
= D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9
deriving stock (Digit
Digit -> Digit -> Bounded Digit
forall a. a -> a -> Bounded a
$cminBound :: Digit
minBound :: Digit
$cmaxBound :: Digit
maxBound :: Digit
Bounded, Int -> Digit
Digit -> Int
Digit -> [Digit]
Digit -> Digit
Digit -> Digit -> [Digit]
Digit -> Digit -> Digit -> [Digit]
(Digit -> Digit)
-> (Digit -> Digit)
-> (Int -> Digit)
-> (Digit -> Int)
-> (Digit -> [Digit])
-> (Digit -> Digit -> [Digit])
-> (Digit -> Digit -> [Digit])
-> (Digit -> Digit -> Digit -> [Digit])
-> Enum Digit
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Digit -> Digit
succ :: Digit -> Digit
$cpred :: Digit -> Digit
pred :: Digit -> Digit
$ctoEnum :: Int -> Digit
toEnum :: Int -> Digit
$cfromEnum :: Digit -> Int
fromEnum :: Digit -> Int
$cenumFrom :: Digit -> [Digit]
enumFrom :: Digit -> [Digit]
$cenumFromThen :: Digit -> Digit -> [Digit]
enumFromThen :: Digit -> Digit -> [Digit]
$cenumFromTo :: Digit -> Digit -> [Digit]
enumFromTo :: Digit -> Digit -> [Digit]
$cenumFromThenTo :: Digit -> Digit -> Digit -> [Digit]
enumFromThenTo :: Digit -> Digit -> Digit -> [Digit]
Enum, Digit -> Digit -> Bool
(Digit -> Digit -> Bool) -> (Digit -> Digit -> Bool) -> Eq Digit
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Digit -> Digit -> Bool
== :: Digit -> Digit -> Bool
$c/= :: Digit -> Digit -> Bool
/= :: Digit -> Digit -> Bool
Eq, (forall x. Digit -> Rep Digit x)
-> (forall x. Rep Digit x -> Digit) -> Generic Digit
forall x. Rep Digit x -> Digit
forall x. Digit -> Rep Digit x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Digit -> Rep Digit x
from :: forall x. Digit -> Rep Digit x
$cto :: forall x. Rep Digit x -> Digit
to :: forall x. Rep Digit x -> Digit
Generic, Eq Digit
Eq Digit =>
(Digit -> Digit -> Ordering)
-> (Digit -> Digit -> Bool)
-> (Digit -> Digit -> Bool)
-> (Digit -> Digit -> Bool)
-> (Digit -> Digit -> Bool)
-> (Digit -> Digit -> Digit)
-> (Digit -> Digit -> Digit)
-> Ord Digit
Digit -> Digit -> Bool
Digit -> Digit -> Ordering
Digit -> Digit -> Digit
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 :: Digit -> Digit -> Ordering
compare :: Digit -> Digit -> Ordering
$c< :: Digit -> Digit -> Bool
< :: Digit -> Digit -> Bool
$c<= :: Digit -> Digit -> Bool
<= :: Digit -> Digit -> Bool
$c> :: Digit -> Digit -> Bool
> :: Digit -> Digit -> Bool
$c>= :: Digit -> Digit -> Bool
>= :: Digit -> Digit -> Bool
$cmax :: Digit -> Digit -> Digit
max :: Digit -> Digit -> Digit
$cmin :: Digit -> Digit -> Digit
min :: Digit -> Digit -> Digit
Ord)
deriving anyclass Eq Digit
KnownNat (Cardinality Digit)
(Eq Digit, KnownNat (Cardinality Digit)) =>
(Finite (Cardinality Digit) -> Digit)
-> (Digit -> Finite (Cardinality Digit))
-> ((1 <= Cardinality Digit) => Digit)
-> ((1 <= Cardinality Digit) => Digit)
-> (Digit -> Maybe Digit)
-> (Digit -> Maybe Digit)
-> Finitary Digit
(1 <= Cardinality Digit) => Digit
Finite (Cardinality Digit) -> Digit
Digit -> Maybe Digit
Digit -> Finite (Cardinality Digit)
forall a.
(Eq a, KnownNat (Cardinality a)) =>
(Finite (Cardinality a) -> a)
-> (a -> Finite (Cardinality a))
-> ((1 <= Cardinality a) => a)
-> ((1 <= Cardinality a) => a)
-> (a -> Maybe a)
-> (a -> Maybe a)
-> Finitary a
$cfromFinite :: Finite (Cardinality Digit) -> Digit
fromFinite :: Finite (Cardinality Digit) -> Digit
$ctoFinite :: Digit -> Finite (Cardinality Digit)
toFinite :: Digit -> Finite (Cardinality Digit)
$cstart :: (1 <= Cardinality Digit) => Digit
start :: (1 <= Cardinality Digit) => Digit
$cend :: (1 <= Cardinality Digit) => Digit
end :: (1 <= Cardinality Digit) => Digit
$cprevious :: Digit -> Maybe Digit
previous :: Digit -> Maybe Digit
$cnext :: Digit -> Maybe Digit
next :: Digit -> Maybe Digit
Finitary
instance Num Digit where
Digit
a + :: Digit -> Digit -> Digit
+ Digit
b = Int -> Digit
forall i. Integral i => i -> Digit
fromIntegral (Digit -> Int
forall a. Enum a => a -> Int
fromEnum Digit
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Digit -> Int
forall a. Enum a => a -> Int
fromEnum Digit
b)
Digit
a * :: Digit -> Digit -> Digit
* Digit
b = Int -> Digit
forall i. Integral i => i -> Digit
fromIntegral (Digit -> Int
forall a. Enum a => a -> Int
fromEnum Digit
a Int -> Int -> Int
forall a. Num a => a -> a -> a
* Digit -> Int
forall a. Enum a => a -> Int
fromEnum Digit
b)
Digit
a - :: Digit -> Digit -> Digit
- Digit
b = Int -> Digit
forall i. Integral i => i -> Digit
fromIntegral (Digit -> Int
forall a. Enum a => a -> Int
fromEnum Digit
a Int -> Int -> Int
forall a. Num a => a -> a -> a
- Digit -> Int
forall a. Enum a => a -> Int
fromEnum Digit
b)
abs :: Digit -> Digit
abs Digit
a = Digit
a
fromInteger :: Integer -> Digit
fromInteger = Integer -> Digit
forall i. Integral i => i -> Digit
fromIntegral
signum :: Digit -> Digit
signum Digit
D0 = Digit
D0
signum Digit
__ = Digit
D1
instance Read Digit where readPrec :: ReadPrec Digit
readPrec = Integer -> Digit
forall a. Num a => Integer -> a
fromInteger (Integer -> Digit) -> ReadPrec Integer -> ReadPrec Digit
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadPrec Integer
forall a. Read a => ReadPrec a
readPrec
instance Show Digit where show :: Digit -> String
show = Int -> String
forall a. Show a => a -> String
show (Int -> String) -> (Digit -> Int) -> Digit -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digit -> Int
forall a. Enum a => a -> Int
fromEnum
fromChar :: Char -> Maybe Digit
fromChar :: Char -> Maybe Digit
fromChar Char
c = String -> Maybe Natural
forall a. Read a => String -> Maybe a
readMaybe [Char
c] Maybe Natural -> (Natural -> Maybe Digit) -> Maybe Digit
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Natural -> Maybe Digit
forall a. Finitary a => Natural -> Maybe a
maybeFinitary
toChar :: Digit -> Char
toChar :: Digit -> Char
toChar Digit
digit = case Digit -> String
forall a. Show a => a -> String
show Digit
digit of
[Char
c] -> Char
c
String
_ -> String -> Char
forall a. HasCallStack => String -> a
error String
"toChar"
fromIntegral :: Integral i => i -> Digit
fromIntegral :: forall i. Integral i => i -> Digit
fromIntegral i
i = Int -> Digit
forall a. Enum a => Int -> a
toEnum (i -> Int
forall a b. (Integral a, Num b) => a -> b
Prelude.fromIntegral (i
i i -> i -> i
forall a. Integral a => a -> a -> a
`mod` i
10))
generate :: MonadRandom m => m Digit
generate :: forall (m :: * -> *). MonadRandom m => m Digit
generate = m Digit
forall (m :: * -> *) a.
(MonadRandom m, Finitary a, 1 <= Cardinality a) =>
m a
randomFinitary
type family FromChar (c :: Char) :: Maybe Digit where
FromChar '0' = Just D0
FromChar '1' = Just D1
FromChar '2' = Just D2
FromChar '3' = Just D3
FromChar '4' = Just D4
FromChar '5' = Just D5
FromChar '6' = Just D6
FromChar '7' = Just D7
FromChar '8' = Just D8
FromChar '9' = Just D9
FromChar _ = Nothing
type family FromNat (n :: Nat) :: Maybe Digit where
FromNat 0 = Just D0
FromNat 1 = Just D1
FromNat 2 = Just D2
FromNat 3 = Just D3
FromNat 4 = Just D4
FromNat 5 = Just D5
FromNat 6 = Just D6
FromNat 7 = Just D7
FromNat 8 = Just D8
FromNat 9 = Just D9
FromNat _ = Nothing
type family ToNat (d :: Digit) :: Nat where
ToNat D0 = 0
ToNat D1 = 1
ToNat D2 = 2
ToNat D3 = 3
ToNat D4 = 4
ToNat D5 = 5
ToNat D6 = 6
ToNat D7 = 7
ToNat D8 = 8
ToNat D9 = 9