module Main where
import ASCII.ListsAndPredicates
import qualified ASCII.Char
import Control.Applicative (Applicative (..))
import Control.Monad (Monad (..))
import Data.Bool (Bool (..))
import Data.Eq (Eq ((==)))
import Data.Function ((.), ($))
import Data.Functor (Functor (..))
import Data.List (filter, intercalate, map, null)
import Data.Semigroup ((<>))
import Numeric.Natural (Natural)
import System.Exit (die)
import System.IO (IO, putStrLn)
import Text.Show (show)
import qualified Data.Char as Char
import qualified Data.List as List
main :: IO ()
main = dieIfFailures $ do
do
let lists = [ all, printableCharacters, controlCodes, letters,
capitalLetters, smallLetters, digits, octDigits,
hexDigits, numbers]
test 1 $ List.all (\xs -> List.sort xs == xs) lists
do
let convert = Char.chr . ASCII.Char.toInt
eq f g = List.all (\x -> f x == g (convert x))
ASCII.Char.allCharacters
test 2 $ eq isControl Char.isControl
test 3 $ eq isSpace Char.isSpace
test 4 $ eq isLower Char.isLower
test 5 $ eq isUpper Char.isUpper
test 6 $ eq isAlpha Char.isAlpha
test 7 $ eq isAlphaNum Char.isAlphaNum
test 8 $ eq isPrint Char.isPrint
test 9 $ eq isDigit Char.isDigit
test 10 $ eq isOctDigit Char.isOctDigit
test 11 $ eq isHexDigit Char.isHexDigit
test 12 $ eq isLetter Char.isLetter
test 13 $ eq isMark Char.isMark
test 14 $ eq isNumber Char.isNumber
test 15 $ eq isPunctuation Char.isPunctuation
test 16 $ eq isSymbol Char.isSymbol
test 17 $ eq isSeparator Char.isSeparator
test 18 $ controlCodes == filter isControl all
test 19 $ printableCharacters == filter isPrint all
test 20 $ letters == filter isLetter all
test 21 $ capitalLetters == filter isUpper all
test 22 $ smallLetters == filter isLower all
test 23 $ digits == filter isDigit all
test 24 $ numbers == filter isNumber all
test 25 $ octDigits == filter isOctDigit all
test 26 $ hexDigits == filter isHexDigit all
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