由于使用'print'而没有(Show a0)的实例类型变量`a0'是不明确的

the*_*eye 8 haskell

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 []
Run Code Online (Sandbox Code Playgroud)

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

main = print $ flatten $ List [Elem 1, Elem 2]
main = print $ flatten $ Elem 1
Run Code Online (Sandbox Code Playgroud)

它给

[1, 2]
[1]
Run Code Online (Sandbox Code Playgroud)

分别.

当我用空List执行它时失败.

main = print $ flatten $ List []
Run Code Online (Sandbox Code Playgroud)

错误信息

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 []
Run Code Online (Sandbox Code Playgroud)

问题

  1. 为什么会失败,我该如何解决这个问题呢?
  2. 我应该更改我的NestedList定义以接受空List吗?如果是这样,我该怎么做.它很混乱.

Don*_*art 16

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

是吗: [] :: [Int]

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

你是.提供类型注释来解析多态性,然后GHC可以调度到正确的show实例.

例如

main = print $ flatten $ List ([] :: [Int])
Run Code Online (Sandbox Code Playgroud)


Ben*_*ood 9

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

好吧,首先,很容易构建一种情况,其中不清楚列表是否为空,无论如何类型检查讨厌查看,它只想查看类型.这使事情变得更简单,因为这意味着在处理值时,您可以确定您已经知道所有类型.

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

ghci> print ([] :: [Int])
[]
ghci> print ([] :: [Char])
""
Run Code Online (Sandbox Code Playgroud)


Nic*_*gez 8

问题是编译器无法知道的类型flatten $ List [].尝试自己弄清楚这个类型,你会看到它[a]适合某些人a,同时print要求它的参数是一个实例Show,并且[a]Showif a的一个实例Show.即使你的列表是空的,所以不需要任何约束a来表示[],编译器也无法知道.

因此,将显式类型注释(对于Show存在的实例的任何类型)应该起作用:

main = print $ flatten $ List ([] :: [NestedList Int])
Run Code Online (Sandbox Code Playgroud)

要么

main = print $ flatten $ List ([] :: [NestedList ()])
Run Code Online (Sandbox Code Playgroud)

要么

main = print fl
  where
    fl :: [()]
    fl = flatten $ List []
Run Code Online (Sandbox Code Playgroud)