我是哈斯凯尔的新手。我读了this回答,我还想测试我的函数类型,如果有办法的话。 以下是一个示例: test.hs
module Test where
import Test.HUnit
test1 = TestCase (assertEqual "test1" 3 (length [1,2,3]))
tests = TestList [test1]
main :: IO Counts
main = runTestTT tests
我正在使用 runghc test.hs
运行代码,我得到了:
Cases: 1 Tried: 1 Errors: 0 Failures: 0
现在,我如何测试length
函数的类型?
我已尝试添加第二个测试test2 = TestCase (assertEqual "test2" "length :: Foldable t => t a -> Int" :type length)
,但我收到错误 test.hs:5:77: parse error on input 'type'
。
由于
答案 0 :(得分:9)
为类型编写测试几乎绝对不是您想要的。由于Haskell是静态类型的,编译器会在编译时自动为您检查类型,而无需运行任何代码或测试。如果length
没有兼容类型,如果您尝试加载代码,则会出现类型错误。
:type
是来自ghci
的特殊命令,而不是实际的Haskell语法。您无法在正常程序中直接使用它。有一些方法可以获得一个代表一种类型的值,但它们有点复杂,而且几乎绝对不是你需要的。
答案 1 :(得分:3)
虽然我同意这个问题的另一个答案,但我认为无论如何都值得直接回答。您可以在测试套件中放置类型断言,如下所示:
module Test where
check_type_of_length :: Foldable t => t a -> Int
check_type_of_length = length
如果length
无法提供您请求的类型,则模块将无法编译。但是,这不是一个完美的测试:如果length
的类型实际上多多态而不是您要求的类型,那么它仍将“通过”;因此,例如,即使undefined
没有完全类型Foldable t => t a -> Int
,仍会编译以下模块。
module Test where
check_type_of_length :: Foldable t => t a -> Int
check_type_of_length = undefined
如果要检查单态类型,我们可以使测试更精确一些。根据@dfeuer的建议,我们的想法是使用Typeable
。这看起来像这样:
module Test where
import Data.Typeable
test_type_of_not :: Bool
test_type_of_not = typeOf not == typeOf (undefined :: Bool -> Bool)
如果not
具有单态类型Bool -> Bool
,则test_type_of_not
将为True
;如果它具有不同的单形类型,则为False
;如果not
突然变成多态,模块将无法编译并出现歧义错误。
我不知道一种类似的方法来测试多态类型不会变得更多态;你可以做一些令人讨厌的事情,比如运行一个简短的bash脚本
echo :t length | ghci
并使用GHC API检查其输出或更直接的内容。但是,像这样的方法可能非常脆弱。