{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

module Taiwan.ID.Digit1289
  ( Digit1289 (..)
  , fromChar
  , toChar
  , toDigit
  , 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.Digit
  ( Digit (..) )
import Taiwan.ID.Utilities
  ( randomFinitary )

-- | Represents a single decimal digit from the set {@1@, @2@, @8@, @9@}.
--
data Digit1289
  = D1289_1 | D1289_2 | D1289_8 | D1289_9
  deriving stock (Digit1289
Digit1289 -> Digit1289 -> Bounded Digit1289
forall a. a -> a -> Bounded a
$cminBound :: Digit1289
minBound :: Digit1289
$cmaxBound :: Digit1289
maxBound :: Digit1289
Bounded, Int -> Digit1289
Digit1289 -> Int
Digit1289 -> [Digit1289]
Digit1289 -> Digit1289
Digit1289 -> Digit1289 -> [Digit1289]
Digit1289 -> Digit1289 -> Digit1289 -> [Digit1289]
(Digit1289 -> Digit1289)
-> (Digit1289 -> Digit1289)
-> (Int -> Digit1289)
-> (Digit1289 -> Int)
-> (Digit1289 -> [Digit1289])
-> (Digit1289 -> Digit1289 -> [Digit1289])
-> (Digit1289 -> Digit1289 -> [Digit1289])
-> (Digit1289 -> Digit1289 -> Digit1289 -> [Digit1289])
-> Enum Digit1289
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 :: Digit1289 -> Digit1289
succ :: Digit1289 -> Digit1289
$cpred :: Digit1289 -> Digit1289
pred :: Digit1289 -> Digit1289
$ctoEnum :: Int -> Digit1289
toEnum :: Int -> Digit1289
$cfromEnum :: Digit1289 -> Int
fromEnum :: Digit1289 -> Int
$cenumFrom :: Digit1289 -> [Digit1289]
enumFrom :: Digit1289 -> [Digit1289]
$cenumFromThen :: Digit1289 -> Digit1289 -> [Digit1289]
enumFromThen :: Digit1289 -> Digit1289 -> [Digit1289]
$cenumFromTo :: Digit1289 -> Digit1289 -> [Digit1289]
enumFromTo :: Digit1289 -> Digit1289 -> [Digit1289]
$cenumFromThenTo :: Digit1289 -> Digit1289 -> Digit1289 -> [Digit1289]
enumFromThenTo :: Digit1289 -> Digit1289 -> Digit1289 -> [Digit1289]
Enum, Digit1289 -> Digit1289 -> Bool
(Digit1289 -> Digit1289 -> Bool)
-> (Digit1289 -> Digit1289 -> Bool) -> Eq Digit1289
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Digit1289 -> Digit1289 -> Bool
== :: Digit1289 -> Digit1289 -> Bool
$c/= :: Digit1289 -> Digit1289 -> Bool
/= :: Digit1289 -> Digit1289 -> Bool
Eq, (forall x. Digit1289 -> Rep Digit1289 x)
-> (forall x. Rep Digit1289 x -> Digit1289) -> Generic Digit1289
forall x. Rep Digit1289 x -> Digit1289
forall x. Digit1289 -> Rep Digit1289 x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Digit1289 -> Rep Digit1289 x
from :: forall x. Digit1289 -> Rep Digit1289 x
$cto :: forall x. Rep Digit1289 x -> Digit1289
to :: forall x. Rep Digit1289 x -> Digit1289
Generic, Eq Digit1289
Eq Digit1289 =>
(Digit1289 -> Digit1289 -> Ordering)
-> (Digit1289 -> Digit1289 -> Bool)
-> (Digit1289 -> Digit1289 -> Bool)
-> (Digit1289 -> Digit1289 -> Bool)
-> (Digit1289 -> Digit1289 -> Bool)
-> (Digit1289 -> Digit1289 -> Digit1289)
-> (Digit1289 -> Digit1289 -> Digit1289)
-> Ord Digit1289
Digit1289 -> Digit1289 -> Bool
Digit1289 -> Digit1289 -> Ordering
Digit1289 -> Digit1289 -> Digit1289
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 :: Digit1289 -> Digit1289 -> Ordering
compare :: Digit1289 -> Digit1289 -> Ordering
$c< :: Digit1289 -> Digit1289 -> Bool
< :: Digit1289 -> Digit1289 -> Bool
$c<= :: Digit1289 -> Digit1289 -> Bool
<= :: Digit1289 -> Digit1289 -> Bool
$c> :: Digit1289 -> Digit1289 -> Bool
> :: Digit1289 -> Digit1289 -> Bool
$c>= :: Digit1289 -> Digit1289 -> Bool
>= :: Digit1289 -> Digit1289 -> Bool
$cmax :: Digit1289 -> Digit1289 -> Digit1289
max :: Digit1289 -> Digit1289 -> Digit1289
$cmin :: Digit1289 -> Digit1289 -> Digit1289
min :: Digit1289 -> Digit1289 -> Digit1289
Ord, ReadPrec [Digit1289]
ReadPrec Digit1289
Int -> ReadS Digit1289
ReadS [Digit1289]
(Int -> ReadS Digit1289)
-> ReadS [Digit1289]
-> ReadPrec Digit1289
-> ReadPrec [Digit1289]
-> Read Digit1289
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Digit1289
readsPrec :: Int -> ReadS Digit1289
$creadList :: ReadS [Digit1289]
readList :: ReadS [Digit1289]
$creadPrec :: ReadPrec Digit1289
readPrec :: ReadPrec Digit1289
$creadListPrec :: ReadPrec [Digit1289]
readListPrec :: ReadPrec [Digit1289]
Read, Int -> Digit1289 -> ShowS
[Digit1289] -> ShowS
Digit1289 -> String
(Int -> Digit1289 -> ShowS)
-> (Digit1289 -> String)
-> ([Digit1289] -> ShowS)
-> Show Digit1289
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Digit1289 -> ShowS
showsPrec :: Int -> Digit1289 -> ShowS
$cshow :: Digit1289 -> String
show :: Digit1289 -> String
$cshowList :: [Digit1289] -> ShowS
showList :: [Digit1289] -> ShowS
Show)
  deriving anyclass Eq Digit1289
KnownNat (Cardinality Digit1289)
(Eq Digit1289, KnownNat (Cardinality Digit1289)) =>
(Finite (Cardinality Digit1289) -> Digit1289)
-> (Digit1289 -> Finite (Cardinality Digit1289))
-> ((1 <= Cardinality Digit1289) => Digit1289)
-> ((1 <= Cardinality Digit1289) => Digit1289)
-> (Digit1289 -> Maybe Digit1289)
-> (Digit1289 -> Maybe Digit1289)
-> Finitary Digit1289
(1 <= Cardinality Digit1289) => Digit1289
Finite (Cardinality Digit1289) -> Digit1289
Digit1289 -> Maybe Digit1289
Digit1289 -> Finite (Cardinality Digit1289)
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 Digit1289) -> Digit1289
fromFinite :: Finite (Cardinality Digit1289) -> Digit1289
$ctoFinite :: Digit1289 -> Finite (Cardinality Digit1289)
toFinite :: Digit1289 -> Finite (Cardinality Digit1289)
$cstart :: (1 <= Cardinality Digit1289) => Digit1289
start :: (1 <= Cardinality Digit1289) => Digit1289
$cend :: (1 <= Cardinality Digit1289) => Digit1289
end :: (1 <= Cardinality Digit1289) => Digit1289
$cprevious :: Digit1289 -> Maybe Digit1289
previous :: Digit1289 -> Maybe Digit1289
$cnext :: Digit1289 -> Maybe Digit1289
next :: Digit1289 -> Maybe Digit1289
Finitary

-- | Attempts to parse a 'Digit1289' from a character.
--
-- Only the characters @'1'@, @'2'@, @'8'@, and @'9'@ are accepted.
--
fromChar :: Char -> Maybe Digit1289
fromChar :: Char -> Maybe Digit1289
fromChar = \case
  Char
'1' -> Digit1289 -> Maybe Digit1289
forall a. a -> Maybe a
Just Digit1289
D1289_1
  Char
'2' -> Digit1289 -> Maybe Digit1289
forall a. a -> Maybe a
Just Digit1289
D1289_2
  Char
'8' -> Digit1289 -> Maybe Digit1289
forall a. a -> Maybe a
Just Digit1289
D1289_8
  Char
'9' -> Digit1289 -> Maybe Digit1289
forall a. a -> Maybe a
Just Digit1289
D1289_9
  Char
_   -> Maybe Digit1289
forall a. Maybe a
Nothing

-- | Converts a 'Digit1289' to a decimal digit character.
--
toChar :: Digit1289 -> Char
toChar :: Digit1289 -> Char
toChar = \case
  Digit1289
D1289_1 -> Char
'1'
  Digit1289
D1289_2 -> Char
'2'
  Digit1289
D1289_8 -> Char
'8'
  Digit1289
D1289_9 -> Char
'9'

-- | Converts a 'Digit1289' to an ordinary 'Digit'.
--
toDigit :: Digit1289 -> Digit
toDigit :: Digit1289 -> Digit
toDigit = \case
  Digit1289
D1289_1 -> Digit
D1
  Digit1289
D1289_2 -> Digit
D2
  Digit1289
D1289_8 -> Digit
D8
  Digit1289
D1289_9 -> Digit
D9

-- | Generates a random 'Digit1289'.
--
generate :: MonadRandom m => m Digit1289
generate :: forall (m :: * -> *). MonadRandom m => m Digit1289
generate = m Digit1289
forall (m :: * -> *) a.
(MonadRandom m, Finitary a, 1 <= Cardinality a) =>
m a
randomFinitary

type family FromChar (c :: Char) :: Maybe Digit1289 where
  FromChar '1' = Just D1289_1
  FromChar '2' = Just D1289_2
  FromChar '8' = Just D1289_8
  FromChar '9' = Just D1289_9
  FromChar _   = Nothing

type family FromNat (n :: Nat) :: Maybe Digit1289 where
  FromNat 1 = Just D1289_1
  FromNat 2 = Just D1289_2
  FromNat 8 = Just D1289_8
  FromNat 9 = Just D1289_9
  FromNat _ = Nothing

type family ToNat (d :: Digit1289) :: Nat where
  ToNat D1289_1 = 1
  ToNat D1289_2 = 2
  ToNat D1289_8 = 8
  ToNat D1289_9 = 9