簡體   English   中英

Haskell中的剛性類型變量錯誤

[英]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]

listMyTree 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 xlist x的其余部分。

list (Branch _ (x:xs))        = list x : map list xs

但是,這是多余的:您將相同的list函數應用於xxs的元素。 這意味着您可以將其簡化為:

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]東西。 我們可以使用一個函數concatconcat (map list xs) ,但是我們可以用concatMap更加慣用地寫它: concatMap list xs

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM