Haskell 没有因使用“print';类型变量'a0';含糊不清

Haskell 没有因使用“print';类型变量'a0';含糊不清,haskell,Haskell,我用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)) mai

我用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 []
它给

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

当我使用空列表执行它时,它会失败

[1, 2]
[1]
错误消息

main = print $ flatten $ List []
问题

  • 为什么它会失败?我如何修复它
  • 我是否应该更改我的
    嵌套列表
    定义以接受空的
    列表
    ?如果是,我该怎么做。这很令人困惑

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

    是:
    []:[Int]

    或者
    []::[可能(两个字符串中的任意一个)]
    。谁说呢

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

    例如


    问题是编译器无法知道展平$List[]的类型。试着自己找出类型,对于某些
    a
    ,你会看到它是
    [a]
    ,而
    print
    要求它的参数是
    Show
    的实例,
    [a]
    Show
    的实例,如果
    a
    Show
    的实例。即使您的列表是空的,所以不需要对
    a
    进行任何约束来表示
    []
    ,编译器也无法知道

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

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


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


    按照错误消息所说的去做,并给出一个明确的类型,如
    ([]:[Int])

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

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

    第二,不管它是什么类型的列表,即使它是空的:

    main = print fl
      where
        fl :: [()]
        fl = flatten $ List []
    

    GHC没有使用哪种类型的信息。当列表中有
    elem1
    时,它提供了
    numa
    约束,然后GHC可以将类型变量默认为
    Integer
    。如果没有元素,则不能默认类型变量
    a0
    。例如,给它一个类型签名,
    main=print$flant$(List[]::NestedList())
    ,这样编译器就知道要使用哪种类型。在
    NestedList
    之后和
    [()]
    中,空参数是什么意思?@theourtheye
    ()
    是一个大小为零的元组。这有点像Haskell的
    void
    。Haskell知道如何打印空元组?是的,因为“()”有一个“Show”实例。与类型为“[a]”的“[]”不同,“()”是类型为“()”,因此任何东西都不会影响打印,“显示”结果始终为“()”。
    main = print $ flatten $ List ([] :: [NestedList Int])
    
    main = print $ flatten $ List ([] :: [NestedList ()])
    
    main = print fl
      where
        fl :: [()]
        fl = flatten $ List []
    
    ghci> print ([] :: [Int])
    []
    ghci> print ([] :: [Char])
    ""