module TuringMachine.ShowedSymbol (
    ShowedSymbol,
    blank,
    isBlank,
    ShowedSymbols,
    ShowedSymbolClass (showedSymbols),
  ) where

import Data.String (IsString (fromString))

data ShowedSymbol =
      Blank
    | JustSymbol String
    deriving (ShowedSymbol -> ShowedSymbol -> Bool
(ShowedSymbol -> ShowedSymbol -> Bool)
-> (ShowedSymbol -> ShowedSymbol -> Bool) -> Eq ShowedSymbol
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ShowedSymbol -> ShowedSymbol -> Bool
$c/= :: ShowedSymbol -> ShowedSymbol -> Bool
== :: ShowedSymbol -> ShowedSymbol -> Bool
$c== :: ShowedSymbol -> ShowedSymbol -> Bool
Eq, Eq ShowedSymbol
Eq ShowedSymbol
-> (ShowedSymbol -> ShowedSymbol -> Ordering)
-> (ShowedSymbol -> ShowedSymbol -> Bool)
-> (ShowedSymbol -> ShowedSymbol -> Bool)
-> (ShowedSymbol -> ShowedSymbol -> Bool)
-> (ShowedSymbol -> ShowedSymbol -> Bool)
-> (ShowedSymbol -> ShowedSymbol -> ShowedSymbol)
-> (ShowedSymbol -> ShowedSymbol -> ShowedSymbol)
-> Ord ShowedSymbol
ShowedSymbol -> ShowedSymbol -> Bool
ShowedSymbol -> ShowedSymbol -> Ordering
ShowedSymbol -> ShowedSymbol -> ShowedSymbol
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
min :: ShowedSymbol -> ShowedSymbol -> ShowedSymbol
$cmin :: ShowedSymbol -> ShowedSymbol -> ShowedSymbol
max :: ShowedSymbol -> ShowedSymbol -> ShowedSymbol
$cmax :: ShowedSymbol -> ShowedSymbol -> ShowedSymbol
>= :: ShowedSymbol -> ShowedSymbol -> Bool
$c>= :: ShowedSymbol -> ShowedSymbol -> Bool
> :: ShowedSymbol -> ShowedSymbol -> Bool
$c> :: ShowedSymbol -> ShowedSymbol -> Bool
<= :: ShowedSymbol -> ShowedSymbol -> Bool
$c<= :: ShowedSymbol -> ShowedSymbol -> Bool
< :: ShowedSymbol -> ShowedSymbol -> Bool
$c< :: ShowedSymbol -> ShowedSymbol -> Bool
compare :: ShowedSymbol -> ShowedSymbol -> Ordering
$ccompare :: ShowedSymbol -> ShowedSymbol -> Ordering
$cp1Ord :: Eq ShowedSymbol
Ord)

instance Show ShowedSymbol where
    show :: ShowedSymbol -> String
show ShowedSymbol
Blank = String
"_"
    show (JustSymbol String
s) = String
s
    showList :: [ShowedSymbol] -> ShowS
showList = String -> ShowS
forall a. [a] -> [a] -> [a]
(++) (String -> ShowS)
-> ([ShowedSymbol] -> String) -> [ShowedSymbol] -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unwords ([String] -> String)
-> ([ShowedSymbol] -> [String]) -> [ShowedSymbol] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ShowedSymbol -> String) -> [ShowedSymbol] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ShowedSymbol -> String
forall a. Show a => a -> String
show

instance Read ShowedSymbol where
    readsPrec :: Int -> ReadS ShowedSymbol
readsPrec Int
_ String
"." = [(ShowedSymbol
Blank, String
"")]
    readsPrec Int
_ String
s = [(String -> ShowedSymbol
JustSymbol String
s, String
"")]
    readList :: ReadS [ShowedSymbol]
readList String
s = [(String -> ShowedSymbol
forall a. Read a => String -> a
read (String -> ShowedSymbol) -> [String] -> [ShowedSymbol]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> [String]
words String
s, String
"")]

blank :: ShowedSymbol
blank :: ShowedSymbol
blank = ShowedSymbol
Blank

instance IsString ShowedSymbol where
    fromString :: String -> ShowedSymbol
fromString = String -> ShowedSymbol
forall a. Read a => String -> a
read

isBlank :: ShowedSymbol -> Bool
isBlank :: ShowedSymbol -> Bool
isBlank ShowedSymbol
Blank = Bool
True
isBlank ShowedSymbol
_ = Bool
False

type ShowedSymbols = [ShowedSymbol]

class ShowedSymbolClass s where
    showedSymbols :: [s] -> ShowedSymbols

instance ShowedSymbolClass Char where
    showedSymbols :: String -> [ShowedSymbol]
showedSymbols String
s
        | Char
' ' Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
s =
            (String -> ShowedSymbol) -> [String] -> [ShowedSymbol]
forall a b. (a -> b) -> [a] -> [b]
map String -> ShowedSymbol
forall a. Read a => String -> a
read ([String] -> [ShowedSymbol]) -> [String] -> [ShowedSymbol]
forall a b. (a -> b) -> a -> b
$ String -> [String]
words String
s
        | Bool
otherwise =
            (Char -> ShowedSymbol) -> String -> [ShowedSymbol]
forall a b. (a -> b) -> [a] -> [b]
map (String -> ShowedSymbol
forall a. Read a => String -> a
read (String -> ShowedSymbol)
-> (Char -> String) -> Char -> ShowedSymbol
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> String
forall (f :: * -> *) a. Applicative f => a -> f a
pure) String
s

instance ShowedSymbolClass ShowedSymbol where
    showedSymbols :: [ShowedSymbol] -> [ShowedSymbol]
showedSymbols = [ShowedSymbol] -> [ShowedSymbol]
forall a. a -> a
id