module Main where import ASCII.Group import ASCII.Char (Char (..), allCharacters) import Control.Applicative (Applicative (..)) import Control.Monad (Monad (..)) import Data.Bool (Bool (..), not) import Data.Eq (Eq ((==))) import Data.Foldable (all) import Data.Function ((.), ($)) import Data.Functor (Functor (..)) import Data.List (intercalate, map, null, length, filter) import Data.Semigroup ((<>)) import Numeric.Natural (Natural) import System.Exit (die) import System.IO (IO, putStrLn) import Text.Show (show) main :: IO () main = dieIfFailures $ do test 1 $ map charGroup [CapitalLetterA, EndOfTransmission] == [Printable, Control] test 2 $ not $ inGroup Printable EndOfTransmission test 3 $ inGroup Control EndOfTransmission test 4 $ charGroup Space == Printable test 5 $ charGroup HorizontalTab == Control test 6 $ all (inGroup Printable) [CapitalLetterA, SmallLetterZ, Digit4, Tilde] test 7 $ all (inGroup Control) [Null, Substitute, UnitSeparator, Delete] test 8 $ length (filter (inGroup Control) allCharacters) == 33 test 9 $ length (filter (inGroup Printable) allCharacters) == 95 dieIfFailures :: Failures a -> IO a dieIfFailures (Failures fs x) = if null fs then do putStrLn "💯"; return x else die $ intercalate " " (map (("🔥" <> ) . show) fs) type TestNumber = Natural test :: TestNumber -> Bool -> Failures () test n t = Failures (if t then [] else [n]) () data Failures a = Failures [TestNumber] a instance Functor Failures where fmap f (Failures a x) = Failures a (f x) instance Applicative Failures where pure x = Failures [] x Failures a f <*> Failures b x = Failures (a <> b) (f x) instance Monad Failures where Failures a x >>= f = let Failures b y = f x in Failures (a <> b) y