{-# LANGUAGE CPP, DataKinds, TypeOperators, ScopedTypeVariables, KindSignatures,
TypeFamilies, UndecidableInstances #-}
{-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}
{-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-}
import Data.List (isInfixOf)
import Data.Proxy
import Data.Type.Bool
import Control.Exception
import Test.Tasty
import Test.Tasty.HUnit
import ErrorTests
import GHC.TypeLits
import GHC.TypeLits.Extra
test1 :: Proxy (GCD 6 8) -> Proxy 2
test1 = id
test2 :: Proxy ((GCD 6 8) + x) -> Proxy (x + (GCD 10 8))
test2 = id
test3 :: Proxy (CLog 3 10) -> Proxy 3
test3 = id
test4 :: Proxy ((CLog 3 10) + x) -> Proxy (x + (CLog 2 7))
test4 = id
test5 :: Proxy (CLog x (x^y)) -> Proxy y
test5 = id
test6 :: Integer
test6 = natVal (Proxy :: Proxy (CLog 6 8))
test7 :: Integer
test7 = natVal (Proxy :: Proxy (CLog 3 10))
test8 :: Integer
test8 = natVal (Proxy :: Proxy ((CLog 2 4) * (3 ^ (CLog 2 4))))
type family Max (x :: Nat) (y :: Nat) :: Nat
where
Max x y = If (x <=? y) y x
test9 :: Integer
test9 = natVal (Proxy :: Proxy (Max (CLog 2 4) (CLog 4 20)))
main :: IO ()
main = defaultMain tests
tests :: TestTree
tests = testGroup "ghc-typelits-natnormalise"
[ testGroup "Basic functionality"
[ testCase "GCD 6 8 ~ 2" $
show (test1 Proxy) @?=
"Proxy"
, testCase "forall x . GCD 6 8 + x ~ x + GCD 10 8" $
show (test2 Proxy) @?=
"Proxy"
, testCase "CLog 3 10 ~ 3" $
show (test3 Proxy) @?=
"Proxy"
, testCase "forall x . CLog 3 10 + x ~ x + CLog 2 7" $
show (test4 Proxy) @?=
"Proxy"
, testCase "forall x>1 . CLog x (x^y) ~ y" $
show (test4 Proxy) @?=
"Proxy"
, testCase "KnownNat (CLog 6 8) ~ 2" $
show test6 @?=
"2"
, testCase "KnownNat (CLog 3 10) ~ 3" $
show test7 @?=
"3"
, testCase "KnownNat ((CLog 2 4) * (3 ^ (CLog 2 4)))) ~ 18" $
show test8 @?=
"18"
, testCase "KnownNat (Max (CLog 2 4) (CLog 4 20)) ~ 3" $
show test9 @?=
"3"
]
, testGroup "errors"
[ testCase "GCD 6 8 ~ 4" $ testFail1 `throws` testFail1Errors
, testCase "GCD 6 8 + x ~ x + GCD 9 6" $ testFail2 `throws` testFail2Errors
, testCase "CLog 3 10 ~ 2" $ testFail3 `throws` testFail3Errors
, testCase "CLog 3 10 + x ~ x + CLog 2 9" $ testFail4 `throws` testFail4Errors
, testCase "CLog 0 4 ~ 100" $ testFail5 `throws` testFail5Errors
, testCase "CLog 1 4 ~ 100" $ testFail5 `throws` testFail5Errors
, testCase "CLog 4 0 ~ 0" $ testFail7 `throws` testFail7Errors
, testCase "CLog 1 (1^y) ~ y" $ testFail8 `throws` testFail8Errors
, testCase "CLog 0 (0^y) ~ y" $ testFail9 `throws` testFail9Errors
, testCase "No instance (KnownNat (CLog 1 4))" $ testFail10 `throws` testFail10Errors
, testCase "No instance (KnownNat (CLog 4 4 - CLog 2 4))" $ testFail11 `throws` testFail11Errors
]
]
-- | Assert that evaluation of the first argument (to WHNF) will throw
-- an exception whose string representation contains the given
-- substrings.
throws :: a -> [String] -> Assertion
throws v xs = do
result <- try (evaluate v)
case result of
Right _ -> assertFailure "No exception!"
#if MIN_VERSION_base(4,9,0)
Left (TypeError msg) ->
#else
Left (ErrorCall msg) ->
#endif
if all (`isInfixOf` msg) xs
then return ()
else assertFailure msg