8
data NestedList a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (Elem element) = [element]
flatten (List []) = []
flatten (List (first:rest)) = flatten first ++ flatten (List (rest))
main = print $ flatten $ List []

我在haskell中编写了上面看到的代码。例如,当我使用任何其他参数执行此操作时

main = print $ flatten $ List [Elem 1, Elem 2]
main = print $ flatten $ Elem 1

它给

[1, 2]
[1]

分别。

当我用一个空列表执行它时它失败了。

main = print $ flatten $ List []

错误信息

No instance for (Show a0) arising from a use of `print'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
  instance Show Double -- Defined in `GHC.Float'
  instance Show Float -- Defined in `GHC.Float'
  instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
    -- Defined in `GHC.Real'
  ...plus 23 others
In the expression: print
In the expression: print $ flatten $ List []
In an equation for `main': main = print $ flatten $ List []

问题

  1. 为什么它会失败,我该如何解决这个问题?
  2. 我应该改变我的NestedList定义来接受一个空的List吗?如果是这样,我该怎么做。它相当混乱。
4

4 回答 4

17

列表类型是多态的。由于您不提供元素,只提供空列表构造函数[],因此无法推断这是什么列表类型。

是吗: [] :: [Int]

[] :: [Maybe (Either String Double)]。谁说?

你是。提供类型注释来解决多态性,然后 GHC 可以分派到正确的显示实例。

例如

main = print $ flatten $ List ([] :: [Int])
于 2013-09-04T13:55:26.180 回答
9

要在这里添加答案,您可能会反对“但是我的列表包含什么类型的东西有什么关系?它没有任何东西!”

好吧,首先,很容易构造一个不清楚列表是否为空的情况,而且类型检查讨厌查看values,它只想查看types。这让事情变得更简单,因为这意味着在处理值时,您可以确定您已经知道所有类型。

其次,它实际上是什么类型的列表很重要,即使它是空的:

ghci> print ([] :: [Int])
[]
ghci> print ([] :: [Char])
""
于 2013-09-04T23:16:52.450 回答
8

问题是编译器无法知道flatten $ List []. 尝试自己找出类型,您会看到它是[a]for some a,同时print要求它的参数是 的实例Show,并且[a]Showifa的实例 的实例Show。即使您的列表是空的,因此不需要对ato 表示任何约束[],编译器也无法知道。

因此,放置显式类型注释(对于Show存在实例的任何类型)应该有效:

main = print $ flatten $ List ([] :: [NestedList Int])

或者

main = print $ flatten $ List ([] :: [NestedList ()])

或者

main = print fl
  where
    fl :: [()]
    fl = flatten $ List []
于 2013-09-04T13:56:20.957 回答
3

[]可以是浮点数、字符串、布尔值或实际上任何类型的列表。因此,print不知道show使用哪个实例。

按照错误消息的说明进行操作并给出明确的类型,如([] :: [Int]).

于 2013-09-04T13:59:30.943 回答