Haskell中的刚性类型变量错误

Haskell中的刚性类型变量错误,haskell,Haskell,为什么会出现刚性类型变量错误: data MyTree a = Leaf [a] | Branch (String, a) [MyTree a] deriving (Show) list :: MyTree a -> [a] list (Leaf []) = [] list (Leaf m) = m list (Branch _ (x:xs)) =

为什么会出现
刚性类型变量
错误:

data MyTree a  = Leaf [a]
               | Branch (String, a) [MyTree a] 
               deriving (Show)


list :: MyTree a -> [a]
list (Leaf [])                = []
list (Leaf m)                 = m
list (Branch _ (x:xs))        = list x ++ map (list) xs

-------------------------------------------------------------
Couldn't match type `a' with `[a]'
      `a' is a rigid type variable bound by
          the type signature for list :: MyTree a -> [a]
          at test.hs:6:15
    Expected type: MyTree a -> a
      Actual type: MyTree a -> [a]
    In the first argument of `map', namely `(list)'
    In the second argument of `(++)', namely `map (list) xs'
    In the expression: list x ++ map (list) xs

错误中真正告诉您发生了什么的部分是:

因此,您提供给
map
的函数类型是错误的。但为什么会这样呢<代码>地图具有以下类型:

map :: (a -> b) -> [a] -> [b]
list
mytreea->[a]
,因此:

map list :: (MyTree a -> [a]) -> [MyTree a] -> [[a]]
这意味着
映射列表xs
将具有类型
[[a]]
。您是这样使用它的:

list x ++ map list xs -- omitting unnecessary parentheses.
(++)
是列表连接;它需要两个相同类型的列表<但是,代码>列表x是
[a]
而不是
[[a]]
,这会导致类型错误。由于
[a]
[[a]]
的元素类型,您可以尝试使用
(:)
,而不是
(++)
,将
列表x
预先添加到列表的其余部分

list (Branch _ (x:xs))        = list x : map list xs
但是,这是多余的:您正在对
x
xs
的元素应用相同的
list
函数。这意味着您可以将其简化为:

list (Branch _ xs)        = map list xs
我们仍然没有完成,因为
映射列表xs
的类型为
[[a]]
,而您需要
[a]
。不过,这很容易解决:只需使用
concatMap
,它映射函数并展平结果列表。然后,完整的定义将变成:

list :: MyTree a -> [a]
list (Leaf m)             = m
list (Branch _ xs)        = concatMap list xs
我已删除多余的
(Leaf[])
案例。请注意,您的函数没有涵盖
(

分支机构[])
案例;这不是一个问题,因为我们没有只匹配
(x:xs)

映射(列表)xs的类型是
[[a]]
,您需要
[a]
类型的东西。我们可以使用一个函数
concat
concat(映射列表xs)
,但是我们可以用
concatMap
更惯用地编写它:
concatMap列表xs

hmm,在
列表(节点x:xs)的代码中还有另一个错误
由于您没有将节点定义为MyTree类型的值构造函数,即您只提供了Leaf和BranchHmm,因此代码仍然被分解为什么是
索引树
?您从未在此代码段中定义过它。代码仍然被破坏,因为您的
分支
值构造函数接受两个参数,但在模式匹配中,您只给
分支
(应该是
分支
)一个参数,即
(x:xs)
占用了(字符串,a),但即使代码是错误的,因为(x:xs)不是用于元组,而是用于列表,其中x是列表的第一个元素。感谢您的详细解释。
list :: MyTree a -> [a]
list (Leaf m)             = m
list (Branch _ xs)        = concatMap list xs