{-# LANGUAGE MagicHash #-} module Main (main) where import Control.Applicative import Data.Maybe import Data.Proxy import Data.Type.Ord (type (<=)) import GHC.Exts (Constraint, proxy#) import System.Exit import Text.Read import KindInteger (P, N) import KindInteger qualified as K -------------------------------------------------------------------------------- data Dict (c :: Constraint) where Dict :: c => Dict c -------------------------------------------------------------------------------- _testEq = Dict _testEq :: Dict ( P 0 K.== P 0, 'True ~ (P 0 K.==? P 0) , N 0 K.== N 0, 'True ~ (N 0 K.==? N 0) , P 0 K.== N 0, 'True ~ (P 0 K.==? N 0) , N 0 K.== P 0, 'True ~ (N 0 K.==? P 0) , P 0 K./= P 1, 'True ~ (P 0 K./=? P 1) , P 0 K./= N 1, 'True ~ (P 0 K./=? N 1) , N 0 K./= N 1, 'True ~ (N 0 K./=? N 1) , N 0 K./= N 1, 'True ~ (N 0 K./=? N 1) , P 1 K./= P 0, 'True ~ (P 1 K./=? P 0) , P 1 K./= N 0, 'True ~ (P 1 K./=? N 0) , N 1 K./= N 0, 'True ~ (N 1 K./=? N 0) , N 1 K./= N 0, 'True ~ (N 1 K./=? N 0) ) _testCmp = Dict _testCmp :: Dict ( P 0 <= P 0 , P 0 <= N 0 , N 0 <= P 0 , N 0 <= N 0 , N 2 <= N 1 , N 1 <= N 0 , N 0 <= P 1 , P 0 <= P 1 , P 1 <= P 2 ) _testAdd = Dict _testAdd :: Dict ( P 0 ~ P 0 K.+ P 0 , P 0 ~ N 0 K.+ N 0 , P 0 ~ P 0 K.+ N 0 , P 0 ~ N 0 K.+ P 0 , P 1 ~ P 1 K.+ P 0 , N 1 ~ N 1 K.+ N 0 , P 1 ~ P 1 K.+ N 0 , N 1 ~ N 1 K.+ P 0 , P 1 ~ P 0 K.+ P 1 , N 1 ~ N 0 K.+ N 1 , N 1 ~ P 0 K.+ N 1 , P 1 ~ N 0 K.+ P 1 , P 2 ~ P 1 K.+ P 1 , N 2 ~ N 1 K.+ N 1 , P 0 ~ P 1 K.+ N 1 , P 0 ~ N 1 K.+ P 1 ) _testMul = Dict _testMul :: Dict ( P 0 ~ P 0 K.* P 0 , P 0 ~ N 0 K.* N 0 , P 0 ~ P 0 K.* N 0 , P 0 ~ N 0 K.* P 0 , P 0 ~ P 1 K.* P 0 , P 0 ~ N 1 K.* N 0 , P 0 ~ P 1 K.* N 0 , P 0 ~ N 1 K.* P 0 , P 0 ~ P 0 K.* P 1 , P 0 ~ N 0 K.* N 1 , P 0 ~ P 0 K.* N 1 , P 0 ~ N 0 K.* P 1 , P 1 ~ P 1 K.* P 1 , P 1 ~ N 1 K.* N 1 , N 1 ~ P 1 K.* N 1 , N 1 ~ N 1 K.* P 1 , P 2 ~ P 2 K.* P 1 , P 2 ~ N 2 K.* N 1 , N 2 ~ P 2 K.* N 1 , N 2 ~ N 2 K.* P 1 , P 6 ~ P 2 K.* P 3 , P 6 ~ N 2 K.* N 3 , N 6 ~ P 2 K.* N 3 , N 6 ~ N 2 K.* P 3 ) _testDiv = Dict _testDiv :: Dict ( P 0 ~ P 0 `K.Div` P 1 , P 0 ~ N 0 `K.Div` N 1 , P 0 ~ P 0 `K.Div` N 1 , P 0 ~ N 0 `K.Div` P 1 , P 1 ~ P 1 `K.Div` P 1 , P 1 ~ N 1 `K.Div` N 1 , N 1 ~ P 1 `K.Div` N 1 , N 1 ~ N 1 `K.Div` P 1 , P 2 ~ P 2 `K.Div` P 1 , P 2 ~ N 2 `K.Div` N 1 , N 2 ~ P 2 `K.Div` N 1 , N 2 ~ N 2 `K.Div` P 1 , P 1 ~ P 2 `K.Div` P 2 , P 1 ~ N 2 `K.Div` N 2 , N 1 ~ P 2 `K.Div` N 2 , N 1 ~ N 2 `K.Div` P 2 , P 1 ~ P 3 `K.Div` P 2 , P 1 ~ N 3 `K.Div` N 2 , N 2 ~ P 3 `K.Div` N 2 , N 2 ~ N 3 `K.Div` P 2 , P 0 ~ P 0 `K.Div` P 1 , P 0 ~ N 0 `K.Div` N 1 , P 0 ~ P 0 `K.Div` N 1 , P 0 ~ N 0 `K.Div` P 1 , P 0 ~ P 1 `K.Div` P 2 , P 0 ~ N 1 `K.Div` N 2 , N 1 ~ P 1 `K.Div` N 2 , N 1 ~ N 1 `K.Div` P 2 ) _testMod = Dict _testMod :: Dict ( P 0 ~ P 0 `K.Mod` P 1 , P 0 ~ N 0 `K.Mod` N 1 , P 0 ~ P 0 `K.Mod` N 1 , P 0 ~ N 0 `K.Mod` P 1 , P 0 ~ P 1 `K.Mod` P 1 , P 0 ~ N 1 `K.Mod` N 1 , P 0 ~ P 1 `K.Mod` N 1 , P 0 ~ N 1 `K.Mod` P 1 , P 0 ~ P 2 `K.Mod` P 1 , P 0 ~ N 2 `K.Mod` N 1 , P 0 ~ P 2 `K.Mod` N 1 , P 0 ~ N 2 `K.Mod` P 1 , P 0 ~ P 2 `K.Mod` P 2 , P 0 ~ N 2 `K.Mod` N 2 , P 0 ~ P 2 `K.Mod` N 2 , P 0 ~ N 2 `K.Mod` P 2 , P 1 ~ P 3 `K.Mod` P 2 , N 1 ~ N 3 `K.Mod` N 2 , N 1 ~ P 3 `K.Mod` N 2 , P 1 ~ N 3 `K.Mod` P 2 , P 0 ~ P 0 `K.Mod` P 1 , P 0 ~ N 0 `K.Mod` N 1 , P 0 ~ P 0 `K.Mod` N 1 , P 0 ~ N 0 `K.Mod` P 1 , P 1 ~ P 1 `K.Mod` P 2 , N 1 ~ N 1 `K.Mod` N 2 , N 1 ~ P 1 `K.Mod` N 2 , P 1 ~ N 1 `K.Mod` P 2 ) _testQuot = Dict _testQuot :: Dict ( P 0 ~ P 0 `K.Quot` P 1 , P 0 ~ N 0 `K.Quot` N 1 , P 0 ~ P 0 `K.Quot` N 1 , P 0 ~ N 0 `K.Quot` P 1 , P 1 ~ P 1 `K.Quot` P 1 , P 1 ~ N 1 `K.Quot` N 1 , N 1 ~ P 1 `K.Quot` N 1 , N 1 ~ N 1 `K.Quot` P 1 , P 2 ~ P 2 `K.Quot` P 1 , P 2 ~ N 2 `K.Quot` N 1 , N 2 ~ P 2 `K.Quot` N 1 , N 2 ~ N 2 `K.Quot` P 1 , P 1 ~ P 2 `K.Quot` P 2 , P 1 ~ N 2 `K.Quot` N 2 , N 1 ~ P 2 `K.Quot` N 2 , N 1 ~ N 2 `K.Quot` P 2 , P 1 ~ P 3 `K.Quot` P 2 , P 1 ~ N 3 `K.Quot` N 2 , N 1 ~ P 3 `K.Quot` N 2 , N 1 ~ N 3 `K.Quot` P 2 , P 0 ~ P 0 `K.Quot` P 1 , P 0 ~ N 0 `K.Quot` N 1 , P 0 ~ P 0 `K.Quot` N 1 , P 0 ~ N 0 `K.Quot` P 1 , P 0 ~ P 1 `K.Quot` P 2 , P 0 ~ N 1 `K.Quot` N 2 , P 0 ~ P 1 `K.Quot` N 2 , P 0 ~ N 1 `K.Quot` P 2 ) _testRem = Dict _testRem :: Dict ( P 0 ~ P 0 `K.Rem` P 1 , P 0 ~ N 0 `K.Rem` N 1 , P 0 ~ P 0 `K.Rem` N 1 , P 0 ~ N 0 `K.Rem` P 1 , P 0 ~ P 1 `K.Rem` P 1 , P 0 ~ N 1 `K.Rem` N 1 , P 0 ~ P 1 `K.Rem` N 1 , P 0 ~ N 1 `K.Rem` P 1 , P 0 ~ P 2 `K.Rem` P 1 , P 0 ~ N 2 `K.Rem` N 1 , P 0 ~ P 2 `K.Rem` N 1 , P 0 ~ N 2 `K.Rem` P 1 , P 0 ~ P 2 `K.Rem` P 2 , P 0 ~ N 2 `K.Rem` N 2 , P 0 ~ P 2 `K.Rem` N 2 , P 0 ~ N 2 `K.Rem` P 2 , P 1 ~ P 3 `K.Rem` P 2 , N 1 ~ N 3 `K.Rem` N 2 , P 1 ~ P 3 `K.Rem` N 2 , N 1 ~ N 3 `K.Rem` P 2 , P 0 ~ P 0 `K.Rem` P 1 , P 0 ~ N 0 `K.Rem` N 1 , P 0 ~ P 0 `K.Rem` N 1 , P 0 ~ N 0 `K.Rem` P 1 , P 1 ~ P 1 `K.Rem` P 2 , N 1 ~ N 1 `K.Rem` N 2 , P 1 ~ P 1 `K.Rem` N 2 , N 1 ~ N 1 `K.Rem` P 2 ) _testLog2 = Dict _testLog2 :: Dict ( P 0 ~ K.Log2 (P 1) , P 1 ~ K.Log2 (P 2) , P 1 ~ K.Log2 (P 3) , P 2 ~ K.Log2 (P 4) , P 2 ~ K.Log2 (P 5) , P 2 ~ K.Log2 (P 6) , P 2 ~ K.Log2 (P 7) , P 3 ~ K.Log2 (P 8) , P 3 ~ K.Log2 (P 9) , P 3 ~ K.Log2 (P 10) , P 3 ~ K.Log2 (P 11) , P 3 ~ K.Log2 (P 12) , P 3 ~ K.Log2 (P 13) , P 3 ~ K.Log2 (P 14) , P 3 ~ K.Log2 (P 15) , P 4 ~ K.Log2 (P 16) , P 4 ~ K.Log2 (P 17) , P 4 ~ K.Log2 (P 18) , P 4 ~ K.Log2 (P 19) , P 4 ~ K.Log2 (P 20) , P 4 ~ K.Log2 (P 21) , P 4 ~ K.Log2 (P 22) , P 4 ~ K.Log2 (P 23) , P 4 ~ K.Log2 (P 24) , P 4 ~ K.Log2 (P 25) , P 4 ~ K.Log2 (P 26) , P 4 ~ K.Log2 (P 27) , P 4 ~ K.Log2 (P 28) , P 4 ~ K.Log2 (P 29) , P 4 ~ K.Log2 (P 30) , P 4 ~ K.Log2 (P 31) , P 5 ~ K.Log2 (P 32) ) -------------------------------------------------------------------------------- assert :: String -- ^ Test name -> Bool -- ^ Successful is true -> IO Bool -- ^ Return the same 'Bool' given as input. assert n x = do putStrLn ((if x then "[OK] " else "[FAIL] ") <> n) pure x testsMain :: [IO Bool] -> IO a testsMain xs = do oks <- sequence xs if and oks then do putStrLn "All tests passed successfully." exitSuccess else do putStrLn "Some tests failed." exitFailure main :: IO () main = testsMain [ assert "integerVal . someIntegerVal == id" $ flip all [-5 .. 5] $ \a -> case K.someIntegerVal a of K.SomeInteger pa -> a == K.integerVal pa , assert "integerVal' . someIntegerVal == id" $ flip all [-5 .. 5] $ \a -> case K.someIntegerVal a of K.SomeInteger (_ :: Proxy a) -> a == K.integerVal' (proxy# @a) , assert "sameIntegerVal a a" $ flip all [-5 .. 5] $ \a -> case K.someIntegerVal a of K.SomeInteger pa -> isJust (K.sameInteger pa pa) , assert "sameIntegerVal a a'" $ flip all [-5 .. 5] $ \a -> case (K.someIntegerVal a, K.someIntegerVal a) of (K.SomeInteger pa1, K.SomeInteger pa2) -> isJust (K.sameInteger pa1 pa2) , assert "sameIntegerVal a b" $ flip all (liftA2 (,) [-5 .. 5] [-5 .. 5])$ \(a, b) -> case (K.someIntegerVal a, K.someIntegerVal b) of (K.SomeInteger pa, K.SomeInteger pb) | a == b -> isJust (K.sameInteger pa pb) | otherwise -> isNothing (K.sameInteger pa pb) , assert "Eq SomeInteger" $ flip all (liftA2 (,) [-5 .. 5] [-5 .. 5])$ \(a, b) -> (a == b) == (K.someIntegerVal a == K.someIntegerVal b) , assert "Ord SomeInteger" $ flip all (liftA2 (,) [-5 .. 5] [-5 .. 5])$ \(a, b) -> (a `compare` b) == (K.someIntegerVal a `compare` K.someIntegerVal b) , assert "Show SomeInteger" $ flip all [-5 .. 5] $ \i -> show i == show (K.someIntegerVal i) , assert "Read SomeInteger" $ flip all [-5 .. 5] $ \i -> let str = show (i :: Integer) in readMaybe @Integer str == fmap (\(K.SomeInteger p) -> K.integerVal p) (readMaybe @K.SomeInteger str) ]