簡體   English   中英

另一個類型錯誤

[英]another type error

為什么不編譯?

append :: [a] -> [a] -> [a]
append xs ys = foldr (:) ys xs

traverse :: a -> [[a]] -> [[a]]
traverse x [[]] = [[x]]
traverse x [(y:ys)] = append [(x:y:ys)] (map (y:) (traverse x [ys]))

comb :: [a] -> [[a]]
comb [] = [[]]
comb (x:[]) = [[x]]
comb (x:y:[]) = [[x,y],[y,x]] 
comb (x:xs) = map (traverse x) (comb xs)

失敗並顯示以下錯誤:

 Couldn't match type `a' with `[a]'
  `a' is a rigid type variable bound by
      the type signature for comb :: [a] -> [[a]] at pr27.hs:10:1
Expected type: [[a]]
  Actual type: [a]
In the first argument of `comb', namely `xs'
In the second argument of `map', namely `(comb xs)'

xs是列表的尾部,因此它是comb的有效參數? 謝謝大衛·克拉姆夫

您的方法comb xs返回類型[[a]] 當傳遞到map (traverse x)traverse x使用[[a]]每個元素(即[a]類型的元素map (traverse x)調用traverse x 但是, traverse x的類型為[[a]] -> [[a]] ,因此此處的traverse不匹配是traverse [[a]]期望值,但您給了它[a]

一些指針:

  • 盡管可能具有教育意義,但您不需要自己的附加函數-您可以使用++
  • 您可能擁有的comb數量比comb []需要的要多-您真的需要的不僅僅是comb []comb (x:xs)嗎?
  • 如所寫, traverse將不匹配包含多個列表的第二個參數

我自己還沒有通過Haskell來解決這個問題,但是我認為最后一點可能是您的主要問題。


編輯:@Kevin Ballard的答案對於您為什么會收到特定類型錯誤當然是正確的。 但是,我認為,更大的問題是,在某些時候,你需要concat -enate(即壓平)組合的列表的列表(實際上排列,如果我理解你的現有代碼),我沒有看到在這里。

作為硬幣的反面,也許導線的類型簽名應該是a -> [a] -> [[a]]

我的建議是保持具體。 類型變量a可以匹配Int,[Int],[[Int]]等,這可能會導致開發初期的混亂。 一旦程序適用於具體類型,通常就很難對任意類型進行概括。

這是您以前的(越野車)程序的具體版本:

append :: [a] -> [a] -> [a]
append xs ys = foldr (:) ys xs

traverse :: Int -> [Int] -> [[Int]]
traverse x [] = [[x]]
traverse x (y:ys) = append [(x:y:ys)] (map (y:) (traverse x ys))

comb :: [Int] -> [[Int]]
comb [] = [[]]
comb (x:[]) = [[x]]
comb (x:y:[]) = [[x,y],[y,x]] 
comb (x:xs) = map (traverse x) (comb xs)

ghci會抱怨最后一行:

Couldn't match expected type `Int' with actual type `[Int]'
Expected type: [Int] -> [Int]
  Actual type: [Int] -> [[Int]]
In the return type of a call of `traverse'
In the first argument of `map', namely `(traverse x)'

看起來比您遇到的更容易理解。 [a]可以表示[Int],[[Int]]等中的任何內容,而[Int]可以表示..好,[Int]。
正如您在上一個問題中所說的那樣,遍歷功能很好:

Main> map (traverse 3) [[1,2],[2,1]]
[[[3,1,2],[1,3,2],[1,2,3]],[[3,2,1],[2,3,1],[2,1,3]]]

類型:

Main> :type map (traverse 3) [[1,2],[2,1]]
map (traverse 3) [[1,2],[2,1]] :: [[[Int]]]

現在,回想一下梳子功能的類型:

comb :: [Int] -> [[Int]]

類型錯誤的原因應該很清楚。 您需要做的就是在最后一行“組合” map的結果,如下所示:

comb (x:xs) = concat $ map (traverse x) (comb xs)

這是(固定)程序的輸出:

Main>  comb [1,2,3]
[[1,2,3],[2,1,3],[2,3,1],[1,3,2],[3,1,2],[3,2,1]] 

現在,您可以嘗試泛化為任意類型。

暫無
暫無

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

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