[英]rigid type variable error in Haskell
為什么這會給出rigid type variable
錯誤:
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
實際上告訴您發生了什么的錯誤部分是:
Expected type: MyTree a -> a Actual type: MyTree a -> [a] In the first argument of `map', namely `(list)'
因此,您為map
提供的函數類型是錯誤的。 但為什么會這樣呢? map
有類型:
map :: (a -> b) -> [a] -> [b]
list
是MyTree a -> [a]
,因此:
map list :: (MyTree a -> [a]) -> [MyTree a] -> [[a]]
這意味着map list xs
將具有類型[[a]]
。 你這樣使用它:
list x ++ map list xs -- omitting unnecessary parentheses.
(++)
是列表連接; 它期望兩個相同類型的列表。 但是, list x
是[a]
而不是[[a]]
,這會導致類型錯誤。 由於[a]
是[[a]]
元素的類型,因此您可以嘗試使用(:)
而不是(++)
將list x
到list x
的其余部分。
list (Branch _ (x:xs)) = list x : map list xs
但是,這是多余的:您將相同的list
函數應用於x
和xs
的元素。 這意味着您可以將其簡化為:
list (Branch _ xs) = map list xs
我們還沒有完成,因為map list xs
有類型[[a]]
,你想要[a]
。 但這很容易解決:只需使用concatMap
,它映射函數並展平生成的列表列表。 完整的定義將變為:
list :: MyTree a -> [a]
list (Leaf m) = m
list (Branch _ xs) = concatMap list xs
我刪除了冗余(Leaf [])
案例。 請注意,您的功能未涵蓋( Branch _ [])
案例; 現在我們不匹配(x:xs)
,這不是問題。
map (list) xs
的類型是[[a]]
,你想要類型[a]
東西。 我們可以使用一個函數concat
: concat (map list xs)
,但是我們可以用concatMap
更加慣用地寫它: concatMap list xs
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.