mockcat-1.0.0.0: test/Test/MockCat/TH/TypeUtilsSpec.hs
{-# LANGUAGE TemplateHaskellQuotes #-}
module Test.MockCat.TH.TypeUtilsSpec (spec) where
import qualified Data.Map.Strict as Map
import Language.Haskell.TH
import Test.Hspec
import Test.MockCat.TH.TypeUtils
spec :: Spec
spec = do
describe "splitApps" $ do
it "expands function type arguments in order" $ do
let a = mkName "a"
ty = AppT (AppT ArrowT (ConT ''Int)) (VarT a)
splitApps ty `shouldBe` (ArrowT, [ConT ''Int, VarT a])
it "decomposes nested type applications into top-level and argument list" $ do
let a = mkName "a"
b = mkName "b"
ty =
AppT
(ConT ''Maybe)
(AppT (AppT (ConT ''Either) (VarT a)) (VarT b))
splitApps ty
`shouldBe` ( ConT ''Maybe
, [AppT (AppT (ConT ''Either) (VarT a)) (VarT b)]
)
it "returns types without application as they are" $ do
splitApps (ConT ''Bool) `shouldBe` (ConT ''Bool, [])
describe "substituteType" $ do
it "replaces VarT with types from the map" $ do
let a = mkName "a"
b = mkName "b"
ty = AppT (VarT a) (VarT b)
subMap =
Map.fromList
[ (a, ConT ''Int)
, (b, ConT ''Bool)
]
substituteType subMap ty `shouldBe` AppT (ConT ''Int) (ConT ''Bool)
it "recursively applies to constraints and body within ForallT" $ do
let a = mkName "a"
b = mkName "b"
ty =
ForallT
[PlainTV a SpecifiedSpec]
[AppT (ConT ''Eq) (VarT a)]
(AppT (VarT b) (VarT a))
subMap =
Map.fromList
[ (a, ConT ''Char)
, (b, ConT ''Maybe)
]
expected =
ForallT
[PlainTV a SpecifiedSpec]
[AppT (ConT ''Eq) (ConT ''Char)]
(AppT (ConT ''Maybe) (ConT ''Char))
substituteType subMap ty `shouldBe` expected
it "leaves type variables not in the map as they are" $ do
let a = mkName "a"
ty = VarT a
substituteType Map.empty ty `shouldBe` VarT a
describe "isNotConstantFunctionType" $ do
it "is True for types containing arrows" $ do
let ty = AppT (AppT ArrowT (ConT ''Int)) (ConT ''Bool)
isNotConstantFunctionType ty `shouldBe` True
it "is False for tuples" $ do
isNotConstantFunctionType (TupleT 0) `shouldBe` False
it "can judge even when wrapped in forall" $ do
let a = mkName "a"
body = AppT (AppT ArrowT (VarT a)) (ConT ''Int)
ty = ForallT [PlainTV a SpecifiedSpec] [] body
isNotConstantFunctionType ty `shouldBe` True