测试函数的类型

时间:2015-09-28 18:44:29

标签: haskell

我是哈斯凯尔的新手。我读了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'

由于

2 个答案:

答案 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检查其输出或更直接的内容。但是,像这样的方法可能非常脆弱。