{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE TypeApplications #-}

-- |
-- Module      : Data.Char.Domino
-- Description : A module that defines domino values, and their unicode equivalent.
-- Maintainer  : hapytexeu+gh@gmail.com
-- Stability   : experimental
-- Portability : POSIX
--
-- A module that defines values for domino pieces, and converts these to unicode characters of the <https://www.unicode.org/charts/PDF/U1F030.pdf 1F030 unicode block>.
module Data.Char.Domino
  ( -- * Data types to represent domino values
    Domino (Domino, Back, leftTop, rightBottom),
    pattern (:|),
    OrientedDomino,
    SimpleDomino,
    ComplexDomino,

    -- * Render domino values
    dominoH,
    dominoH',
    dominoV,
    dominoV',
    domino,
    domino',

    -- * Convert from 'Char'acters
    fromDomino,
    fromDomino',
  )
where

import Control.DeepSeq (NFData, NFData1)
import Control.Monad ((>=>))
import Data.Char (chr, ord)
import Data.Char.Core (MirrorHorizontal (mirrorHorizontal), MirrorVertical (mirrorVertical), Orientation (Horizontal, Vertical), Oriented (Oriented), UnicodeCharacter (fromUnicodeChar, fromUnicodeChar', isInCharRange, toUnicodeChar), UnicodeText (isInTextRange), generateIsInTextRange')
import Data.Char.Dice (DieValue)
import Data.Data (Data)
import Data.Function (on)
import Data.Functor.Classes (Eq1 (liftEq), Ord1 (liftCompare))
import Data.Hashable (Hashable)
import Data.Hashable.Lifted (Hashable1)
#if __GLASGOW_HASKELL__ < 803
import Data.Semigroup((<>))
#endif

import GHC.Generics (Generic, Generic1)
import Test.QuickCheck.Arbitrary (Arbitrary (arbitrary), Arbitrary1 (liftArbitrary), arbitrary1)
import Test.QuickCheck.Gen (frequency)

-- | A domino piece, which has two items. Depending on the orientation, the
-- items are located at the /top/ and /bottom/; or /left/ and /right/.
data Domino a
  = -- | The front side of the domino piece.
    Domino
      { -- | The part that is located at the /left/ side in case the piece is located /horizontally/, or at the /top/ in case the piece is located /vertically/.
        forall a. Domino a -> a
leftTop :: a,
        -- | The part that is located at the /right/ side in case the piece is located /horizontally/, or at the /bottom/ in case the piece is located /vertically/.
        forall a. Domino a -> a
rightBottom :: a
      }
  | -- | The back side of the domino piece.
    Back
  deriving (Typeable (Domino a)
Typeable (Domino a)
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Domino a -> c (Domino a))
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (Domino a))
-> (Domino a -> Constr)
-> (Domino a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (Domino a)))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (Domino a)))
-> ((forall b. Data b => b -> b) -> Domino a -> Domino a)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Domino a -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Domino a -> r)
-> (forall u. (forall d. Data d => d -> u) -> Domino a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Domino a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Domino a -> m (Domino a))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Domino a -> m (Domino a))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Domino a -> m (Domino a))
-> Data (Domino a)
Domino a -> Constr
Domino a -> DataType
(forall b. Data b => b -> b) -> Domino a -> Domino a
forall {a}. Data a => Typeable (Domino a)
forall a. Data a => Domino a -> Constr
forall a. Data a => Domino a -> DataType
forall a.
Data a =>
(forall b. Data b => b -> b) -> Domino a -> Domino a
forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> Domino a -> u
forall a u.
Data a =>
(forall d. Data d => d -> u) -> Domino a -> [u]
forall a r r'.
Data a =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Domino a -> r
forall a r r'.
Data a =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Domino a -> r
forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> Domino a -> m (Domino a)
forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Domino a -> m (Domino a)
forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Domino a)
forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Domino a -> c (Domino a)
forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Domino a))
forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Domino a))
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) -> Domino a -> u
forall u. (forall d. Data d => d -> u) -> Domino a -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Domino a -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Domino a -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Domino a -> m (Domino a)
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Domino a -> m (Domino a)
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Domino a)
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Domino a -> c (Domino a)
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Domino a))
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Domino a))
$cgfoldl :: forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Domino a -> c (Domino a)
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Domino a -> c (Domino a)
$cgunfold :: forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Domino a)
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Domino a)
$ctoConstr :: forall a. Data a => Domino a -> Constr
toConstr :: Domino a -> Constr
$cdataTypeOf :: forall a. Data a => Domino a -> DataType
dataTypeOf :: Domino a -> DataType
$cdataCast1 :: forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Domino a))
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Domino a))
$cdataCast2 :: forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Domino a))
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Domino a))
$cgmapT :: forall a.
Data a =>
(forall b. Data b => b -> b) -> Domino a -> Domino a
gmapT :: (forall b. Data b => b -> b) -> Domino a -> Domino a
$cgmapQl :: forall a r r'.
Data a =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Domino a -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Domino a -> r
$cgmapQr :: forall a r r'.
Data a =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Domino a -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Domino a -> r
$cgmapQ :: forall a u.
Data a =>
(forall d. Data d => d -> u) -> Domino a -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> Domino a -> [u]
$cgmapQi :: forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> Domino a -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Domino a -> u
$cgmapM :: forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> Domino a -> m (Domino a)
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Domino a -> m (Domino a)
$cgmapMp :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Domino a -> m (Domino a)
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Domino a -> m (Domino a)
$cgmapMo :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Domino a -> m (Domino a)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Domino a -> m (Domino a)
Data, Domino a -> Domino a -> Bool
(Domino a -> Domino a -> Bool)
-> (Domino a -> Domino a -> Bool) -> Eq (Domino a)
forall a. Eq a => Domino a -> Domino a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Domino a -> Domino a -> Bool
== :: Domino a -> Domino a -> Bool
$c/= :: forall a. Eq a => Domino a -> Domino a -> Bool
/= :: Domino a -> Domino a -> Bool
Eq, (forall m. Monoid m => Domino m -> m)
-> (forall m a. Monoid m => (a -> m) -> Domino a -> m)
-> (forall m a. Monoid m => (a -> m) -> Domino a -> m)
-> (forall a b. (a -> b -> b) -> b -> Domino a -> b)
-> (forall a b. (a -> b -> b) -> b -> Domino a -> b)
-> (forall b a. (b -> a -> b) -> b -> Domino a -> b)
-> (forall b a. (b -> a -> b) -> b -> Domino a -> b)
-> (forall a. (a -> a -> a) -> Domino a -> a)
-> (forall a. (a -> a -> a) -> Domino a -> a)
-> (forall a. Domino a -> [a])
-> (forall a. Domino a -> Bool)
-> (forall a. Domino a -> Int)
-> (forall a. Eq a => a -> Domino a -> Bool)
-> (forall a. Ord a => Domino a -> a)
-> (forall a. Ord a => Domino a -> a)
-> (forall a. Num a => Domino a -> a)
-> (forall a. Num a => Domino a -> a)
-> Foldable Domino
forall a. Eq a => a -> Domino a -> Bool
forall a. Num a => Domino a -> a
forall a. Ord a => Domino a -> a
forall m. Monoid m => Domino m -> m
forall a. Domino a -> Bool
forall a. Domino a -> Int
forall a. Domino a -> [a]
forall a. (a -> a -> a) -> Domino a -> a
forall m a. Monoid m => (a -> m) -> Domino a -> m
forall b a. (b -> a -> b) -> b -> Domino a -> b
forall a b. (a -> b -> b) -> b -> Domino a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
$cfold :: forall m. Monoid m => Domino m -> m
fold :: forall m. Monoid m => Domino m -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> Domino a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> Domino a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> Domino a -> m
foldMap' :: forall m a. Monoid m => (a -> m) -> Domino a -> m
$cfoldr :: forall a b. (a -> b -> b) -> b -> Domino a -> b
foldr :: forall a b. (a -> b -> b) -> b -> Domino a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> Domino a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> Domino a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> Domino a -> b
foldl :: forall b a. (b -> a -> b) -> b -> Domino a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> Domino a -> b
foldl' :: forall b a. (b -> a -> b) -> b -> Domino a -> b
$cfoldr1 :: forall a. (a -> a -> a) -> Domino a -> a
foldr1 :: forall a. (a -> a -> a) -> Domino a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> Domino a -> a
foldl1 :: forall a. (a -> a -> a) -> Domino a -> a
$ctoList :: forall a. Domino a -> [a]
toList :: forall a. Domino a -> [a]
$cnull :: forall a. Domino a -> Bool
null :: forall a. Domino a -> Bool
$clength :: forall a. Domino a -> Int
length :: forall a. Domino a -> Int
$celem :: forall a. Eq a => a -> Domino a -> Bool
elem :: forall a. Eq a => a -> Domino a -> Bool
$cmaximum :: forall a. Ord a => Domino a -> a
maximum :: forall a. Ord a => Domino a -> a
$cminimum :: forall a. Ord a => Domino a -> a
minimum :: forall a. Ord a => Domino a -> a
$csum :: forall a. Num a => Domino a -> a
sum :: forall a. Num a => Domino a -> a
$cproduct :: forall a. Num a => Domino a -> a
product :: forall a. Num a => Domino a -> a
Foldable, (forall a b. (a -> b) -> Domino a -> Domino b)
-> (forall a b. a -> Domino b -> Domino a) -> Functor Domino
forall a b. a -> Domino b -> Domino a
forall a b. (a -> b) -> Domino a -> Domino b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> Domino a -> Domino b
fmap :: forall a b. (a -> b) -> Domino a -> Domino b
$c<$ :: forall a b. a -> Domino b -> Domino a
<$ :: forall a b. a -> Domino b -> Domino a
Functor, (forall x. Domino a -> Rep (Domino a) x)
-> (forall x. Rep (Domino a) x -> Domino a) -> Generic (Domino a)
forall x. Rep (Domino a) x -> Domino a
forall x. Domino a -> Rep (Domino a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Domino a) x -> Domino a
forall a x. Domino a -> Rep (Domino a) x
$cfrom :: forall a x. Domino a -> Rep (Domino a) x
from :: forall x. Domino a -> Rep (Domino a) x
$cto :: forall a x. Rep (Domino a) x -> Domino a
to :: forall x. Rep (Domino a) x -> Domino a
Generic, (forall a. Domino a -> Rep1 Domino a)
-> (forall a. Rep1 Domino a -> Domino a) -> Generic1 Domino
forall a. Rep1 Domino a -> Domino a
forall a. Domino a -> Rep1 Domino a
forall k (f :: k -> *).
(forall (a :: k). f a -> Rep1 f a)
-> (forall (a :: k). Rep1 f a -> f a) -> Generic1 f
$cfrom1 :: forall a. Domino a -> Rep1 Domino a
from1 :: forall a. Domino a -> Rep1 Domino a
$cto1 :: forall a. Rep1 Domino a -> Domino a
to1 :: forall a. Rep1 Domino a -> Domino a
Generic1, Eq (Domino a)
Eq (Domino a)
-> (Domino a -> Domino a -> Ordering)
-> (Domino a -> Domino a -> Bool)
-> (Domino a -> Domino a -> Bool)
-> (Domino a -> Domino a -> Bool)
-> (Domino a -> Domino a -> Bool)
-> (Domino a -> Domino a -> Domino a)
-> (Domino a -> Domino a -> Domino a)
-> Ord (Domino a)
Domino a -> Domino a -> Bool
Domino a -> Domino a -> Ordering
Domino a -> Domino a -> Domino 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 (Domino a)
forall a. Ord a => Domino a -> Domino a -> Bool
forall a. Ord a => Domino a -> Domino a -> Ordering
forall a. Ord a => Domino a -> Domino a -> Domino a
$ccompare :: forall a. Ord a => Domino a -> Domino a -> Ordering
compare :: Domino a -> Domino a -> Ordering
$c< :: forall a. Ord a => Domino a -> Domino a -> Bool
< :: Domino a -> Domino a -> Bool
$c<= :: forall a. Ord a => Domino a -> Domino a -> Bool
<= :: Domino a -> Domino a -> Bool
$c> :: forall a. Ord a => Domino a -> Domino a -> Bool
> :: Domino a -> Domino a -> Bool
$c>= :: forall a. Ord a => Domino a -> Domino a -> Bool
>= :: Domino a -> Domino a -> Bool
$cmax :: forall a. Ord a => Domino a -> Domino a -> Domino a
max :: Domino a -> Domino a -> Domino a
$cmin :: forall a. Ord a => Domino a -> Domino a -> Domino a
min :: Domino a -> Domino a -> Domino a
Ord, ReadPrec [Domino a]
ReadPrec (Domino a)
Int -> ReadS (Domino a)
ReadS [Domino a]
(Int -> ReadS (Domino a))
-> ReadS [Domino a]
-> ReadPrec (Domino a)
-> ReadPrec [Domino a]
-> Read (Domino a)
forall a. Read a => ReadPrec [Domino a]
forall a. Read a => ReadPrec (Domino a)
forall a. Read a => Int -> ReadS (Domino a)
forall a. Read a => ReadS [Domino a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: forall a. Read a => Int -> ReadS (Domino a)
readsPrec :: Int -> ReadS (Domino a)
$creadList :: forall a. Read a => ReadS [Domino a]
readList :: ReadS [Domino a]
$creadPrec :: forall a. Read a => ReadPrec (Domino a)
readPrec :: ReadPrec (Domino a)
$creadListPrec :: forall a. Read a => ReadPrec [Domino a]
readListPrec :: ReadPrec [Domino a]
Read, Int -> Domino a -> ShowS
[Domino a] -> ShowS
Domino a -> String
(Int -> Domino a -> ShowS)
-> (Domino a -> String) -> ([Domino a] -> ShowS) -> Show (Domino a)
forall a. Show a => Int -> Domino a -> ShowS
forall a. Show a => [Domino a] -> ShowS
forall a. Show a => Domino a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Domino a -> ShowS
showsPrec :: Int -> Domino a -> ShowS
$cshow :: forall a. Show a => Domino a -> String
show :: Domino a -> String
$cshowList :: forall a. Show a => [Domino a] -> ShowS
showList :: [Domino a] -> ShowS
Show, Functor Domino
Foldable Domino
Functor Domino
-> Foldable Domino
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> Domino a -> f (Domino b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    Domino (f a) -> f (Domino a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> Domino a -> m (Domino b))
-> (forall (m :: * -> *) a.
    Monad m =>
    Domino (m a) -> m (Domino a))
-> Traversable Domino
forall (t :: * -> *).
Functor t
-> Foldable t
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a. Monad m => Domino (m a) -> m (Domino a)
forall (f :: * -> *) a.
Applicative f =>
Domino (f a) -> f (Domino a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Domino a -> m (Domino b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Domino a -> f (Domino b)
$ctraverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Domino a -> f (Domino b)
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Domino a -> f (Domino b)
$csequenceA :: forall (f :: * -> *) a.
Applicative f =>
Domino (f a) -> f (Domino a)
sequenceA :: forall (f :: * -> *) a.
Applicative f =>
Domino (f a) -> f (Domino a)
$cmapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Domino a -> m (Domino b)
mapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Domino a -> m (Domino b)
$csequence :: forall (m :: * -> *) a. Monad m => Domino (m a) -> m (Domino a)
sequence :: forall (m :: * -> *) a. Monad m => Domino (m a) -> m (Domino a)
Traversable)

instance Eq1 Domino where
  liftEq :: forall a b. (a -> b -> Bool) -> Domino a -> Domino b -> Bool
liftEq a -> b -> Bool
cmp (Domino a
lta a
rba) (Domino b
ltb b
rbb) = a -> b -> Bool
cmp a
lta b
ltb Bool -> Bool -> Bool
&& a -> b -> Bool
cmp a
rba b
rbb
  liftEq a -> b -> Bool
_ Domino a
Back Domino b
Back = Bool
True
  liftEq a -> b -> Bool
_ Domino a
_ Domino b
_ = Bool
False

instance Hashable1 Domino

instance Hashable a => Hashable (Domino a)

instance NFData a => NFData (Domino a)

instance NFData1 Domino

instance Ord1 Domino where
  liftCompare :: forall a b.
(a -> b -> Ordering) -> Domino a -> Domino b -> Ordering
liftCompare a -> b -> Ordering
cmp (Domino a
lta a
rba) (Domino b
ltb b
rbb) = a -> b -> Ordering
cmp a
lta b
ltb Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> a -> b -> Ordering
cmp a
rba b
rbb
  liftCompare a -> b -> Ordering
_ (Domino a
_ a
_) Domino b
Back = Ordering
LT
  liftCompare a -> b -> Ordering
_ Domino a
Back Domino b
Back = Ordering
EQ
  liftCompare a -> b -> Ordering
_ Domino a
Back (Domino b
_ b
_) = Ordering
GT

-- | A pattern synonym that makes it more convenient to write expressions that
-- look like domino's like for example @II :| IV@.
pattern (:|) ::
  -- | The item that is located at the left, or the top.
  a ->
  -- | The item that is located at the right, or the bottom.
  a ->
  -- | The domino that is constructed.
  Domino a
pattern $m:| :: forall {r} {a}. Domino a -> (a -> a -> r) -> ((# #) -> r) -> r
$b:| :: forall a. a -> a -> Domino a
(:|) x y = Domino x y

-- | A type alias that specifies that 'OrientedDomino' is an 'Oriented' type
-- that wraps a 'Domino' item.
type OrientedDomino a = Oriented (Domino a)

-- | A 'SimpleDomino' is a 'Domino' that contains 'DieValue' objects, it thus
-- can not have an "empty" value.
type SimpleDomino = Domino DieValue

-- | A 'ComplexDomino' is a 'Domino' that contains 'Maybe' values wrapping a
-- 'DieValue'. In case of a 'Nothing', that side is considered /empty/.
type ComplexDomino = Domino (Maybe DieValue)

instance Applicative Domino where
  pure :: forall a. a -> Domino a
pure a
x = a -> a -> Domino a
forall a. a -> a -> Domino a
Domino a
x a
x
  Domino a -> b
fa a -> b
fb <*> :: forall a b. Domino (a -> b) -> Domino a -> Domino b
<*> Domino a
a a
b = b -> b -> Domino b
forall a. a -> a -> Domino a
Domino (a -> b
fa a
a) (a -> b
fb a
b)
  Domino (a -> b)
_ <*> Domino a
_ = Domino b
forall a. Domino a
Back

instance Arbitrary a => Arbitrary (Domino a) where
  arbitrary :: Gen (Domino a)
arbitrary = Gen (Domino a)
forall (f :: * -> *) a. (Arbitrary1 f, Arbitrary a) => Gen (f a)
arbitrary1

instance Arbitrary1 Domino where
  liftArbitrary :: forall a. Gen a -> Gen (Domino a)
liftArbitrary Gen a
arb = [(Int, Gen (Domino a))] -> Gen (Domino a)
forall a. [(Int, Gen a)] -> Gen a
frequency [(Int
1, Domino a -> Gen (Domino a)
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Domino a
forall a. Domino a
Back), (Int
3, a -> a -> Domino a
forall a. a -> a -> Domino a
Domino (a -> a -> Domino a) -> Gen a -> Gen (a -> Domino a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
arb Gen (a -> Domino a) -> Gen a -> Gen (Domino a)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen a
arb)]

instance Bounded a => Bounded (Domino a) where
  minBound :: Domino a
minBound = a -> a -> Domino a
forall a. a -> a -> Domino a
Domino a
forall a. Bounded a => a
minBound a
forall a. Bounded a => a
minBound
  maxBound :: Domino a
maxBound = Domino a
forall a. Domino a
Back

_offsetDominoHorizontal :: Int
_offsetDominoHorizontal :: Int
_offsetDominoHorizontal = Int
0x1f030

_offsetDominoVertical :: Int
_offsetDominoVertical :: Int
_offsetDominoVertical = Int
0x1f062

_domino :: Int -> ComplexDomino -> Char
_domino :: Int -> ComplexDomino -> Char
_domino Int
n = ComplexDomino -> Char
forall {a}. Enum a => Domino (Maybe a) -> Char
go
  where
    go :: Domino (Maybe a) -> Char
go Domino (Maybe a)
Back = Int -> Char
chr Int
n
    go (Domino Maybe a
a Maybe a
b) = Int -> Char
chr (Int
7 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Maybe a -> Int
forall {a}. Enum a => Maybe a -> Int
_val Maybe a
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Maybe a -> Int
forall {a}. Enum a => Maybe a -> Int
_val Maybe a
b Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
    _val :: Maybe a -> Int
_val Maybe a
Nothing = Int
0
    _val (Just a
x) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a. Enum a => a -> Int
fromEnum a
x

_fromDomino :: Int -> ComplexDomino
_fromDomino :: Int -> ComplexDomino
_fromDomino (-1) = ComplexDomino
forall a. Domino a
Back
_fromDomino Int
n = (Maybe DieValue -> Maybe DieValue -> ComplexDomino)
-> (Int -> Maybe DieValue) -> Int -> Int -> ComplexDomino
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
on Maybe DieValue -> Maybe DieValue -> ComplexDomino
forall a. a -> a -> Domino a
Domino Int -> Maybe DieValue
forall {a}. Enum a => Int -> Maybe a
go Int
a Int
b
  where
    (Int
a, Int
b) = Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
quotRem Int
n Int
7
    go :: Int -> Maybe a
go Int
0 = Maybe a
forall a. Maybe a
Nothing
    go Int
k = a -> Maybe a
forall a. a -> Maybe a
Just (Int -> a
forall a. Enum a => Int -> a
toEnum (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1))

-- | Convert the given 'Char'acter to an 'Oriented' 'ComplexDomino' object. If
-- the given 'Char'acter is not a valid domino character, the result is
-- unspecified.
fromDomino' ::
  -- | The given 'Char'acter to convert to an 'Oriented' 'ComplexDomino' object.
  Char ->
  -- | The equivalent 'Oriented' 'ComplexDomino' object for the given 'Char'acter.
  Oriented ComplexDomino
fromDomino' :: Char -> Oriented ComplexDomino
fromDomino' = Int -> Oriented ComplexDomino
go (Int -> Oriented ComplexDomino)
-> (Char -> Int) -> Char -> Oriented ComplexDomino
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
ord
  where
    go :: Int -> Oriented ComplexDomino
go Int
n
      | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
_offsetDominoVertical = Int -> Int -> Orientation -> Oriented ComplexDomino
go' Int
_offsetDominoVertical Int
n Orientation
Vertical
      | Bool
otherwise = Int -> Int -> Orientation -> Oriented ComplexDomino
go' Int
_offsetDominoHorizontal Int
n Orientation
Horizontal
    go' :: Int -> Int -> Orientation -> Oriented ComplexDomino
go' Int
k = ComplexDomino -> Orientation -> Oriented ComplexDomino
forall a. a -> Orientation -> Oriented a
Oriented (ComplexDomino -> Orientation -> Oriented ComplexDomino)
-> (Int -> ComplexDomino)
-> Int
-> Orientation
-> Oriented ComplexDomino
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ComplexDomino
_fromDomino (Int -> ComplexDomino) -> (Int -> Int) -> Int -> ComplexDomino
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int
forall a. Enum a => a -> a
pred (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Int
forall a. Num a => a -> a -> a
subtract Int
k

-- | Convert the given 'Char'acter to an 'Oriented' 'ComplexDomino' object. If
-- the given 'Char'acter wrapped in a 'Just' data constructor if the 'Char'acter
-- is a valid domino character; otherwise 'Nothing'.
fromDomino ::
  -- | The given 'Char'acter to convert to an 'Oriented' 'ComplexDomino' object.
  Char ->
  -- | The equivalent 'Oriented' 'ComplexDomino' object for the given 'Char'acter wrapped in a 'Just'; 'Nothing' if the character is not a domino character.
  Maybe (Oriented ComplexDomino)
fromDomino :: Char -> Maybe (Oriented ComplexDomino)
fromDomino Char
c
  | Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
< Char
'\x1f030' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
> Char
'\x1f093' = Maybe (Oriented ComplexDomino)
forall a. Maybe a
Nothing
  | Bool
otherwise = Oriented ComplexDomino -> Maybe (Oriented ComplexDomino)
forall a. a -> Maybe a
Just (Char -> Oriented ComplexDomino
fromDomino' Char
c)

toSimple :: Domino (Maybe a) -> Maybe (Domino a)
toSimple :: forall a. Domino (Maybe a) -> Maybe (Domino a)
toSimple Domino (Maybe a)
Back = Domino a -> Maybe (Domino a)
forall a. a -> Maybe a
Just Domino a
forall a. Domino a
Back
toSimple (Domino (Just a
a) (Just a
b)) = Domino a -> Maybe (Domino a)
forall a. a -> Maybe a
Just (a -> a -> Domino a
forall a. a -> a -> Domino a
Domino a
a a
b)
toSimple Domino (Maybe a)
_ = Maybe (Domino a)
forall a. Maybe a
Nothing

-- | Convert a 'ComplexDomino' value to a unicode character rendering the domino
-- value /horizontally/.
dominoH ::
  -- | The 'ComplexDomino' object to render horizontally.
  ComplexDomino ->
  -- | The unicode character that represents the given 'ComplexDomino' value in a horizontal manner.
  Char
dominoH :: ComplexDomino -> Char
dominoH = Int -> ComplexDomino -> Char
_domino Int
_offsetDominoHorizontal

-- | Convert a 'SimpleDomino' value to a unicode character rendering the domino
-- value /horizontally/.
dominoH' ::
  -- | The 'SimpleDomino' object to render horizontally.
  SimpleDomino ->
  -- | The unicode character that represents the given 'SimpleDomino' value in a horizontal manner.
  Char
dominoH' :: SimpleDomino -> Char
dominoH' = ComplexDomino -> Char
dominoH (ComplexDomino -> Char)
-> (SimpleDomino -> ComplexDomino) -> SimpleDomino -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (DieValue -> Maybe DieValue) -> SimpleDomino -> ComplexDomino
forall a b. (a -> b) -> Domino a -> Domino b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap DieValue -> Maybe DieValue
forall a. a -> Maybe a
Just

-- | Convert a 'ComplexDomino' value to a unicode character rendering the domino
-- value /vertically/.
dominoV ::
  -- | The 'ComplexDomino' object to render vertically.
  ComplexDomino ->
  -- | The unicode character that represents the given 'ComplexDomino' value in a vertical manner.
  Char
dominoV :: ComplexDomino -> Char
dominoV = Int -> ComplexDomino -> Char
_domino Int
_offsetDominoVertical

-- | Convert a 'SimpleDomino' value to a unicode character rendering the domino
-- value /vertically/.
dominoV' ::
  -- | The 'SimpleDomino' object to render vertically.
  SimpleDomino ->
  -- | The unicode character that represents the given 'SimpleDomino' value in vertical manner.
  Char
dominoV' :: SimpleDomino -> Char
dominoV' = ComplexDomino -> Char
dominoV (ComplexDomino -> Char)
-> (SimpleDomino -> ComplexDomino) -> SimpleDomino -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (DieValue -> Maybe DieValue) -> SimpleDomino -> ComplexDomino
forall a b. (a -> b) -> Domino a -> Domino b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap DieValue -> Maybe DieValue
forall a. a -> Maybe a
Just

-- | Convert an 'OrientedDomino' to its unicode equivalent, where the sides of
-- the domino can be empty.
domino ::
  -- | The 'OrientedDomino' to render.
  OrientedDomino (Maybe DieValue) ->
  -- | The unicode characters that represents the 'OrientedDomino' value.
  Char
domino :: Oriented ComplexDomino -> Char
domino (Oriented ComplexDomino
d Orientation
Horizontal) = ComplexDomino -> Char
dominoH ComplexDomino
d
domino (Oriented ComplexDomino
d Orientation
Vertical) = ComplexDomino -> Char
dominoV ComplexDomino
d

-- | Convert an 'OrientedDomino' to its unicode equivalent, where the sides of
-- the domino can /not/ be empty.
domino' ::
  -- | The 'OrientedDomino' to render.
  OrientedDomino DieValue ->
  -- | The unicode characters that represents the 'OrientedDomino' value.
  Char
domino' :: OrientedDomino DieValue -> Char
domino' = Oriented ComplexDomino -> Char
domino (Oriented ComplexDomino -> Char)
-> (OrientedDomino DieValue -> Oriented ComplexDomino)
-> OrientedDomino DieValue
-> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SimpleDomino -> ComplexDomino)
-> OrientedDomino DieValue -> Oriented ComplexDomino
forall a b. (a -> b) -> Oriented a -> Oriented b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((DieValue -> Maybe DieValue) -> SimpleDomino -> ComplexDomino
forall a b. (a -> b) -> Domino a -> Domino b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap DieValue -> Maybe DieValue
forall a. a -> Maybe a
Just)

instance UnicodeCharacter (Oriented (Domino (Maybe DieValue))) where
  toUnicodeChar :: Oriented ComplexDomino -> Char
toUnicodeChar = Oriented ComplexDomino -> Char
domino
  fromUnicodeChar :: Char -> Maybe (Oriented ComplexDomino)
fromUnicodeChar = Char -> Maybe (Oriented ComplexDomino)
fromDomino
  fromUnicodeChar' :: Char -> Oriented ComplexDomino
fromUnicodeChar' = Char -> Oriented ComplexDomino
fromDomino'
  isInCharRange :: Char -> Bool
isInCharRange Char
c = Char
'\x1f030' 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
'\x1f093'

instance MirrorHorizontal (Oriented (Domino a)) where
  mirrorHorizontal :: Oriented (Domino a) -> Oriented (Domino a)
mirrorHorizontal (Oriented (Domino a
a a
b) Orientation
Vertical) = Domino a -> Orientation -> Oriented (Domino a)
forall a. a -> Orientation -> Oriented a
Oriented (a -> a -> Domino a
forall a. a -> a -> Domino a
Domino a
b a
a) Orientation
Vertical
  mirrorHorizontal o :: Oriented (Domino a)
o@(Oriented Domino a
Back Orientation
_) = Oriented (Domino a)
o
  mirrorHorizontal o :: Oriented (Domino a)
o@(Oriented Domino a
_ Orientation
Horizontal) = Oriented (Domino a)
o

instance MirrorVertical (Oriented (Domino a)) where
  mirrorVertical :: Oriented (Domino a) -> Oriented (Domino a)
mirrorVertical (Oriented (Domino a
a a
b) Orientation
Horizontal) = Domino a -> Orientation -> Oriented (Domino a)
forall a. a -> Orientation -> Oriented a
Oriented (a -> a -> Domino a
forall a. a -> a -> Domino a
Domino a
b a
a) Orientation
Horizontal
  mirrorVertical o :: Oriented (Domino a)
o@(Oriented Domino a
Back Orientation
_) = Oriented (Domino a)
o
  mirrorVertical o :: Oriented (Domino a)
o@(Oriented Domino a
_ Orientation
Vertical) = Oriented (Domino a)
o

instance UnicodeCharacter (Oriented (Domino DieValue)) where
  toUnicodeChar :: OrientedDomino DieValue -> Char
toUnicodeChar = OrientedDomino DieValue -> Char
domino'
  fromUnicodeChar :: Char -> Maybe (OrientedDomino DieValue)
fromUnicodeChar = Char -> Maybe (Oriented ComplexDomino)
fromDomino (Char -> Maybe (Oriented ComplexDomino))
-> (Oriented ComplexDomino -> Maybe (OrientedDomino DieValue))
-> Char
-> Maybe (OrientedDomino DieValue)
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> (ComplexDomino -> Maybe SimpleDomino)
-> Oriented ComplexDomino -> Maybe (OrientedDomino DieValue)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Oriented a -> f (Oriented b)
traverse ComplexDomino -> Maybe SimpleDomino
forall a. Domino (Maybe a) -> Maybe (Domino a)
toSimple
  isInCharRange :: Char -> Bool
isInCharRange Char
c = Char
'\x1f030' 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
'\x1f093' Bool -> Bool -> Bool
&& Bool
go
    where
      x :: Int
x = Char -> Int
ord Char
c
      go :: Bool
go
        | Char
'\x1f031' 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
'\x1f038' = Bool
False
        | Char
'\x1f063' 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
'\x1f06a' = Bool
False
        | Int
x Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
7 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
3 Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x1f062' = Bool
False
        | Int
x Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
7 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
4 Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x1f062' = Bool
False
        | Bool
otherwise = Bool
True

instance UnicodeText (Oriented (Domino (Maybe DieValue))) where
  isInTextRange :: Text -> Bool
isInTextRange = forall a. UnicodeCharacter a => Text -> Bool
generateIsInTextRange' @(Oriented (Domino (Maybe DieValue)))

instance UnicodeText (Oriented (Domino DieValue)) where
  isInTextRange :: Text -> Bool
isInTextRange = forall a. UnicodeCharacter a => Text -> Bool
generateIsInTextRange' @(Oriented (Domino DieValue))