{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE TypeApplications #-}

-- |
-- Module      : Data.Char.BallotBox
-- Description : Support for the ballot box characters in unicode.
-- Maintainer  : hapytexeu+gh@gmail.com
-- Stability   : experimental
-- Portability : POSIX
--
-- Unicode has a <https://www.unicode.org/charts/PDF/U2600.pdf block> named /Miscellaneous Symbols/ that includes unicode characters for boxes that are empty, contain a check or a cross, this module aims to make it more convenient to render these.
module Data.Char.BallotBox
  ( -- * Represent a ballot box.
    BallotBox (Empty, Check, Cross),

    -- * Convert a boolean to a ballot box.
    toCheckBox,
    toCrossBox,
  )
where

import Control.DeepSeq (NFData)
import Data.Char.Core (UnicodeCharacter (fromUnicodeChar, fromUnicodeChar', isInCharRange, toUnicodeChar), UnicodeText (isInTextRange), generateIsInTextRange', mapFromEnum, mapToEnum, mapToEnumSafe)
import Data.Data (Data)
import Data.Hashable (Hashable)
import GHC.Generics (Generic)
import Test.QuickCheck.Arbitrary (Arbitrary (arbitrary), arbitraryBoundedEnum)

_ballotOffset :: Int
_ballotOffset :: Int
_ballotOffset = Int
0x2610

-- | Check if the given 'Char'acter is a character that maps on a 'BallotBox' object.
isBallotBox ::
  -- | The given 'Char'acter to check.
  Char ->
  -- | 'True' if the given 'Char'acter corresponds to a 'BallotBox' object; 'False' otherwise.
  Bool
isBallotBox :: Char -> Bool
isBallotBox Char
c = Char
'\x2610' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
c Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x2612'

-- | A datatype that represents the different types of ballot boxes.
data BallotBox
  = -- | The box is /empty/, this is represented with ☐.
    Empty
  | -- | The box has a /check/, this is represented with ☑.
    Check
  | -- | The box has a /cross/, this is represented with ☒.
    Cross
  deriving (BallotBox
BallotBox -> BallotBox -> Bounded BallotBox
forall a. a -> a -> Bounded a
$cminBound :: BallotBox
minBound :: BallotBox
$cmaxBound :: BallotBox
maxBound :: BallotBox
Bounded, Typeable BallotBox
Typeable BallotBox
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> BallotBox -> c BallotBox)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c BallotBox)
-> (BallotBox -> Constr)
-> (BallotBox -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c BallotBox))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c BallotBox))
-> ((forall b. Data b => b -> b) -> BallotBox -> BallotBox)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> BallotBox -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> BallotBox -> r)
-> (forall u. (forall d. Data d => d -> u) -> BallotBox -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> BallotBox -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> BallotBox -> m BallotBox)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BallotBox -> m BallotBox)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BallotBox -> m BallotBox)
-> Data BallotBox
BallotBox -> Constr
BallotBox -> DataType
(forall b. Data b => b -> b) -> BallotBox -> BallotBox
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> BallotBox -> u
forall u. (forall d. Data d => d -> u) -> BallotBox -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BallotBox -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BallotBox -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BallotBox -> m BallotBox
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BallotBox -> m BallotBox
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BallotBox
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BallotBox -> c BallotBox
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BallotBox)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c BallotBox)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BallotBox -> c BallotBox
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BallotBox -> c BallotBox
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BallotBox
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BallotBox
$ctoConstr :: BallotBox -> Constr
toConstr :: BallotBox -> Constr
$cdataTypeOf :: BallotBox -> DataType
dataTypeOf :: BallotBox -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BallotBox)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BallotBox)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c BallotBox)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c BallotBox)
$cgmapT :: (forall b. Data b => b -> b) -> BallotBox -> BallotBox
gmapT :: (forall b. Data b => b -> b) -> BallotBox -> BallotBox
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BallotBox -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BallotBox -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BallotBox -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BallotBox -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> BallotBox -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> BallotBox -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> BallotBox -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> BallotBox -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BallotBox -> m BallotBox
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BallotBox -> m BallotBox
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BallotBox -> m BallotBox
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BallotBox -> m BallotBox
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BallotBox -> m BallotBox
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BallotBox -> m BallotBox
Data, Int -> BallotBox
BallotBox -> Int
BallotBox -> [BallotBox]
BallotBox -> BallotBox
BallotBox -> BallotBox -> [BallotBox]
BallotBox -> BallotBox -> BallotBox -> [BallotBox]
(BallotBox -> BallotBox)
-> (BallotBox -> BallotBox)
-> (Int -> BallotBox)
-> (BallotBox -> Int)
-> (BallotBox -> [BallotBox])
-> (BallotBox -> BallotBox -> [BallotBox])
-> (BallotBox -> BallotBox -> [BallotBox])
-> (BallotBox -> BallotBox -> BallotBox -> [BallotBox])
-> Enum BallotBox
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 :: BallotBox -> BallotBox
succ :: BallotBox -> BallotBox
$cpred :: BallotBox -> BallotBox
pred :: BallotBox -> BallotBox
$ctoEnum :: Int -> BallotBox
toEnum :: Int -> BallotBox
$cfromEnum :: BallotBox -> Int
fromEnum :: BallotBox -> Int
$cenumFrom :: BallotBox -> [BallotBox]
enumFrom :: BallotBox -> [BallotBox]
$cenumFromThen :: BallotBox -> BallotBox -> [BallotBox]
enumFromThen :: BallotBox -> BallotBox -> [BallotBox]
$cenumFromTo :: BallotBox -> BallotBox -> [BallotBox]
enumFromTo :: BallotBox -> BallotBox -> [BallotBox]
$cenumFromThenTo :: BallotBox -> BallotBox -> BallotBox -> [BallotBox]
enumFromThenTo :: BallotBox -> BallotBox -> BallotBox -> [BallotBox]
Enum, BallotBox -> BallotBox -> Bool
(BallotBox -> BallotBox -> Bool)
-> (BallotBox -> BallotBox -> Bool) -> Eq BallotBox
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BallotBox -> BallotBox -> Bool
== :: BallotBox -> BallotBox -> Bool
$c/= :: BallotBox -> BallotBox -> Bool
/= :: BallotBox -> BallotBox -> Bool
Eq, (forall x. BallotBox -> Rep BallotBox x)
-> (forall x. Rep BallotBox x -> BallotBox) -> Generic BallotBox
forall x. Rep BallotBox x -> BallotBox
forall x. BallotBox -> Rep BallotBox x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. BallotBox -> Rep BallotBox x
from :: forall x. BallotBox -> Rep BallotBox x
$cto :: forall x. Rep BallotBox x -> BallotBox
to :: forall x. Rep BallotBox x -> BallotBox
Generic, Eq BallotBox
Eq BallotBox
-> (BallotBox -> BallotBox -> Ordering)
-> (BallotBox -> BallotBox -> Bool)
-> (BallotBox -> BallotBox -> Bool)
-> (BallotBox -> BallotBox -> Bool)
-> (BallotBox -> BallotBox -> Bool)
-> (BallotBox -> BallotBox -> BallotBox)
-> (BallotBox -> BallotBox -> BallotBox)
-> Ord BallotBox
BallotBox -> BallotBox -> Bool
BallotBox -> BallotBox -> Ordering
BallotBox -> BallotBox -> BallotBox
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 :: BallotBox -> BallotBox -> Ordering
compare :: BallotBox -> BallotBox -> Ordering
$c< :: BallotBox -> BallotBox -> Bool
< :: BallotBox -> BallotBox -> Bool
$c<= :: BallotBox -> BallotBox -> Bool
<= :: BallotBox -> BallotBox -> Bool
$c> :: BallotBox -> BallotBox -> Bool
> :: BallotBox -> BallotBox -> Bool
$c>= :: BallotBox -> BallotBox -> Bool
>= :: BallotBox -> BallotBox -> Bool
$cmax :: BallotBox -> BallotBox -> BallotBox
max :: BallotBox -> BallotBox -> BallotBox
$cmin :: BallotBox -> BallotBox -> BallotBox
min :: BallotBox -> BallotBox -> BallotBox
Ord, ReadPrec [BallotBox]
ReadPrec BallotBox
Int -> ReadS BallotBox
ReadS [BallotBox]
(Int -> ReadS BallotBox)
-> ReadS [BallotBox]
-> ReadPrec BallotBox
-> ReadPrec [BallotBox]
-> Read BallotBox
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS BallotBox
readsPrec :: Int -> ReadS BallotBox
$creadList :: ReadS [BallotBox]
readList :: ReadS [BallotBox]
$creadPrec :: ReadPrec BallotBox
readPrec :: ReadPrec BallotBox
$creadListPrec :: ReadPrec [BallotBox]
readListPrec :: ReadPrec [BallotBox]
Read, Int -> BallotBox -> ShowS
[BallotBox] -> ShowS
BallotBox -> String
(Int -> BallotBox -> ShowS)
-> (BallotBox -> String)
-> ([BallotBox] -> ShowS)
-> Show BallotBox
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BallotBox -> ShowS
showsPrec :: Int -> BallotBox -> ShowS
$cshow :: BallotBox -> String
show :: BallotBox -> String
$cshowList :: [BallotBox] -> ShowS
showList :: [BallotBox] -> ShowS
Show)

instance Hashable BallotBox

instance NFData BallotBox

-- | Convert the given 'Bool'ean to a 'BallotBox' that is 'Empty', or contains a 'Check'.
toCheckBox ::
  -- | The given 'Bool' that determines if the box contains a 'Check'.
  Bool ->
  -- | The corresponding 'BallotBox'.
  BallotBox
toCheckBox :: Bool -> BallotBox
toCheckBox = Int -> BallotBox
forall a. Enum a => Int -> a
toEnum (Int -> BallotBox) -> (Bool -> Int) -> Bool -> BallotBox
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Int
forall a. Enum a => a -> Int
fromEnum

-- | Convert the given 'Bool'ean to a 'BallotBox' that is 'Empty', or contains a 'Cross'.
toCrossBox ::
  -- | The given 'Bool' that determines if the box contains a 'Cross'.
  Bool ->
  -- | The corresponding 'BallotBox'.
  BallotBox
toCrossBox :: Bool -> BallotBox
toCrossBox = Int -> BallotBox
forall a. Enum a => Int -> a
toEnum (Int -> BallotBox) -> (Bool -> Int) -> Bool -> BallotBox
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
*) (Int -> Int) -> (Bool -> Int) -> Bool -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Int
forall a. Enum a => a -> Int
fromEnum

instance Arbitrary BallotBox where
  arbitrary :: Gen BallotBox
arbitrary = Gen BallotBox
forall a. (Bounded a, Enum a) => Gen a
arbitraryBoundedEnum

instance UnicodeCharacter BallotBox where
  toUnicodeChar :: BallotBox -> Char
toUnicodeChar = Int -> BallotBox -> Char
forall a. Enum a => Int -> a -> Char
mapFromEnum Int
_ballotOffset
  fromUnicodeChar :: Char -> Maybe BallotBox
fromUnicodeChar = Int -> Char -> Maybe BallotBox
forall a. (Bounded a, Enum a) => Int -> Char -> Maybe a
mapToEnumSafe Int
_ballotOffset
  fromUnicodeChar' :: Char -> BallotBox
fromUnicodeChar' = Int -> Char -> BallotBox
forall a. Enum a => Int -> Char -> a
mapToEnum Int
_ballotOffset
  isInCharRange :: Char -> Bool
isInCharRange = Char -> Bool
isBallotBox

instance UnicodeText BallotBox where
  isInTextRange :: Text -> Bool
isInTextRange = forall a. UnicodeCharacter a => Text -> Bool
generateIsInTextRange' @BallotBox