[英]Couldn't match expected type `(t1, t2, t0)' with actual type `[a0]`
I'm trying to solve a fractional knapsack problem with the input, 我正在尝试用输入法解决小背包问题,
[("label 1", value, weight), ("label 2", value, weight), ...]
and the output, 和输出,
[("label 1", value, solution_weight), ("label 2", value, solution_weight), ...]
but I keep getting the error in computeKnapsack
: 但是我不断在
computeKnapsack
得到错误:
"Couldn't match expected type `(t1, t2, t0)' with actual type `[a0]`"
I can't understand what the problem might be. 我不明白可能是什么问题。 I'm trying to create a list of 3-entry tuples.
我正在尝试创建3项元组的列表。 How can I get it to stop expecting a single 3-entry tuple?
我如何才能停止期望一个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))))
In the then
branch of computeKnapsack
the result is a single 3-tuple, but in the else
branch it is a list of 3-tuples. 在
computeKnapsack
的then
分支中,结果是单个3元组,但是在else
分支中,结果是3元组列表。
I'm going to rewrite computeKnapsack
for you. 我将为您重写
computeKnapsack
。 I'll start with your version with the error fixed: 我将从您的版本开始,并修复错误:
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))))
First, I'm going to say what happens if the first argument to computeKnapsack
is the empty list: 首先,我要说一下,如果
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))))
It enables us to get rid of the if
-test, making the code shorter overall and easier to understand. 它使我们摆脱了
if
-test,使代码总体上更短并且更易于理解。
Next, I'll deconstruct x
: 接下来,我将解构
x
:
computeKnapsack [] _ = []
computeKnapsack ((a,b,_,d):xs) weightLeft =
(a, b, ((floor (weightLeft / d))*d)) : (computeKnapsack xs (weightLeft-(floor (weightLeft / d)*d)))
You might prefer to follow leftaroundabout's suggestion to create a record type with meaningful names instead. 您可能更喜欢遵循leftaboutabout的建议来创建具有有意义名称的记录类型。 But if you do continue to use a tuple, deconstructing it by pattern matching is much clearer than using your
fst4
, snd4
etc functions. 但是,如果您确实继续使用元组,则通过模式匹配对其进行解构比使用
fst4
, snd4
等函数要清晰得多。
Again, the code is now shorter and easier to understand, though it might help if we used more meaningful names than a
, b
, and d
. 同样,现在的代码更短了,更容易理解,尽管如果我们使用比
a
, b
和d
更有意义的名称可能会有所帮助。
We can continue in this vein: 我们可以继续这样:
computeKnapsack [] _ = []
computeKnapsack ((a,b,_,d):xs) weightLeft = (a, b, weight) : (computeKnapsack xs (weightLeft - weight))
where weight = floor (weightLeft / d) * d
Here I've spotted that the same value was being calculated in two different places, and extracted that value into its own named variable. 在这里,我发现正在两个不同的位置计算相同的值,并将该值提取到其自己的命名变量中。
weight
only needs to be calculated once instead of twice, so computeKnapsack
is now marginally more efficient. weight
只需要计算一次,而无需计算两次,因此现在, computeKnapsack
效率computeKnapsack
。 More importantly, I now understand what computeKnapsack
is doing. 更重要的是,我现在了解了
computeKnapsack
在做什么。
I understand that you're new to Haskell. 我了解您是Haskell的新手。 Please take this as constructive suggestions on how you can write clearer Haskell code.
请将此作为关于如何编写更清晰的Haskell代码的建设性建议。
I've taken the liberty of cleaning up your computeKnapsack
function so you can more clearly see the problem: 我已经清理了您的
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)
My changes were purely cosmetic. 我的改变纯粹是表面上的。 Even after my changes your
computeKnapsack
function is still broken, a bad algorithm, and bad coding style. 即使在更改之后,您的
computeKnapsack
函数仍然损坏,算法错误且编码风格错误。
You can see from the rewritten version that your if
statement has two branches, one returns a tuple, and the other returns a list of tuples. 从重写的版本中可以看到,
if
语句具有两个分支,一个分支返回一个元组,另一个分支返回一个元组列表。 You can fix it simply by changing the first branch to return a list with a single element: 您可以简单地通过更改第一个分支以返回包含单个元素的列表来解决此问题:
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)
Also, before you submit a third question to StackOverflow, please take the time to complete an introductory tutorial to Haskell like http://learnyouahaskell.com/ which will help fix a lot of your problems. 另外,在向StackOverflow提交第三个问题之前,请花些时间完成Haskell入门教程,例如http://learnyouahaskell.com/ ,这将有助于解决许多问题。
One problem that throws that error in in the then of fractionalKnapsack
. 一个问题在
fractionalKnapsack
背包中抛出该错误。 In that line you call function computeKnapsack
with a tuple as the input instead of a list
. 在该行中,您以元组(而不是
list
作为输入调用函数computeKnapsack
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.