3

我写了一个类似于 LISP 的函数flatten

data NestedList a = Elem a | List [NestedList a]

flatten :: NestedList a -> [a]
flatten (Elem x) = [x]
flatten (List xs) = concatMap flatten xs

这两个测试用例工作正常:

test1 = TestCase (assertEqual "test singleton" [5] (flatten (Elem 5)))
test2 = TestCase (assertEqual "test mixed" 
                              [1,2,3,4]
                              (flatten (List [Elem 1, 
                                              List [Elem 2, Elem 3],
                                              Elem 4])))

然而,这个报告一个类型错误:

test3 = TestCase (assertEqual "test empty" [] (flatten (List [])))

REPL 的测试工作正常:

*Main> [] == flatten (List [])
True

为什么会出现错误,我应该如何为空列表编写测试用例?

编辑:这是确切的错误消息:

Ambiguous type variable `a0' in the constraints:
  (Show a0) arising from a use of `assertEqual'
            at D:\haskell\source.hs:61:19-29
  (Eq a0) arising from a use of `assertEqual'
          at D:\haskell\source.hs:61:19-29
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `TestCase', namely
  `(assertEqual "test empty" [] (flatten (List [])))'
4

2 回答 2

7

我猜问题是编译器无法确定空列表的类型。它可能是[Int],,[Char]任何东西。尝试给它一些类型,哪种类型并不重要。

test3 = TestCase (assertEqual "test empty" ([] :: [Int]) (flatten (List [])))

请注意,在其他情况下,编译器可以推断出列表的类型。

于 2011-03-23T20:20:24.290 回答
2

正如错误消息已经告诉您的那样,您必须在单元测试的列表中添加类型签名。可能是这样的:

test3 = TestCase (assertEqual "test empty" ([]::[()]) (flatten (List [])))
于 2011-03-23T20:20:40.650 回答