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

次の 2 つのテスト ケースは正常に動作します。

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 に答える