簡體   English   中英

無法將預期類型“(t1,t2,t0)”與實際類型“ [a0]”匹配

[英]Couldn't match expected type `(t1, t2, t0)' with actual type `[a0]`

我正在嘗試用輸入法解決小背包問題,

[("label 1", value, weight), ("label 2", value, weight), ...]

和輸出,

[("label 1", value, solution_weight), ("label 2", value, solution_weight), ...]

但是我不斷在computeKnapsack得到錯誤:

"Couldn't match expected type `(t1, t2, t0)' with actual type `[a0]`"

我不明白可能是什么問題。 我正在嘗試創建3項元組的列表。 我如何才能停止期望一個3項元組呢?

fst3 (a,b,c) = a
snd3 (a,b,c) = b
trd3 (a,b,c) = c
fst4 (a,b,c,d) = a
snd4 (a,b,c,d) = b
trd4 (a,b,c,d) = c
qud4 (a,b,c,d) = d

sortFrac (a1, b1, c1, d1) (a2, b2, c2, d2)
  | d1 > d2 = GT
  | d1 <= d2 = LT

fracKnap (x:xs) =
    fractionalKnapsack (x:xs) []

fractionalKnapsack (x:xs) fracList =
    if length (x:xs) <= 1
        then computeKnapsack (sortBy sortFrac (((fst3 x),(snd3 x),(trd3 x),(snd3 x) / (trd3 x)):fracList)) 100
        else fractionalKnapsack xs (((fst3 x),(snd3 x),(trd3 x),(snd3 x) / (trd3 x)):fracList)

computeKnapsack (x:xs) weightLeft =
    if length (x:xs) <= 1
        then (fst4 x, snd4 x, ((floor (weightLeft / (qud4 x)))*(qud4 x)))
        else (fst4 x, snd4 x, ((floor (weightLeft / (qud4 x)))*(qud4 x))):(computeKnapsack xs (weightLeft-(floor (weightLeft / (qud4 x))*(qud4 x))))

computeKnapsackthen分支中,結果是單個3元組,但是在else分支中,結果是3元組列表。


我將為您重寫computeKnapsack 我將從您的版本開始,並修復錯誤:

computeKnapsack (x:xs) weightLeft =
    if length (x:xs) <= 1
        then [(fst4 x, snd4 x, ((floor (weightLeft / (qud4 x)))*(qud4 x)))]
        else  (fst4 x, snd4 x, ((floor (weightLeft / (qud4 x)))*(qud4 x))) : (computeKnapsack xs (weightLeft-(floor (weightLeft / (qud4 x))*(qud4 x))))

首先,我要說一下,如果computeKnapsack的第一個參數是空列表,將會發生什么:

computeKnapsack []     _          = []
computeKnapsack (x:xs) weightLeft =
    (fst4 x, snd4 x, ((floor (weightLeft / (qud4 x)))*(qud4 x))) : (computeKnapsack xs (weightLeft-(floor (weightLeft / (qud4 x))*(qud4 x))))

它使我們擺脫了if -test,使代碼總體上更短並且更易於理解。

接下來,我將解構x

computeKnapsack []             _          = []
computeKnapsack ((a,b,_,d):xs) weightLeft =
    (a, b, ((floor (weightLeft / d))*d)) : (computeKnapsack xs (weightLeft-(floor (weightLeft / d)*d)))

您可能更喜歡遵循leftaboutabout的建議來創建具有有意義名稱的記錄類型。 但是,如果您確實繼續使用元組,則通過模式匹配對其進行解構比使用fst4snd4等函數要清晰得多。

同樣,現在的代碼更短了,更容易理解,盡管如果我們使用比abd更有意義的名稱可能會有所幫助。

我們可以繼續這樣:

computeKnapsack []             _          = []
computeKnapsack ((a,b,_,d):xs) weightLeft = (a, b, weight) : (computeKnapsack xs (weightLeft - weight))
  where weight = floor (weightLeft / d) * d

在這里,我發現正在兩個不同的位置計算相同的值,並將該值提取到其自己的命名變量中。 weight只需要計算一次,而無需計算兩次,因此現在, computeKnapsack效率computeKnapsack 更重要的是,我現在了解了computeKnapsack在做什么。

我了解您是Haskell的新手。 請將此作為關於如何編寫更清晰的Haskell代碼的建設性建議。

我已經清理了您的computeKnapsack函數,這樣您就可以更清楚地看到問題所在:

computeKnapsack (x:xs) weightLeft =
 let e = (fst4 x, snd4 x, floor (weightLeft / qud4 x) * qud4 x)
  in if length (x:xs) <= 1
     then e
     else e:computeKnapsack xs (weightLeft - floor (weightLeft / qud4 x) * qud4 x)

我的改變純粹是表面上的。 即使在更改之后,您的computeKnapsack函數仍然損壞,算法錯誤且編碼風格錯誤。

從重寫的版本中可以看到, if語句具有兩個分支,一個分支返回一個元組,另一個分支返回一個元組列表。 您可以簡單地通過更改第一個分支以返回包含單個元素的列表來解決此問題:

computeKnapsack (x:xs) weightLeft =
 let e = (fst4 x, snd4 x, floor (weightLeft / qud4 x) * qud4 x)
  in if length (x:xs) <= 1
     then [e]
     else e:computeKnapsack xs (weightLeft - floor (weightLeft / qud4 x) * qud4 x)

另外,在向StackOverflow提交第三個問題之前,請花些時間完成Haskell入門教程,例如http://learnyouahaskell.com/ ,這將有助於解決許多問題。

一個問題在fractionalKnapsack背包中拋出該錯誤。 在該行中,您以元組(而不是list作為輸入調用函數computeKnapsack

暫無
暫無

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

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