我有两个功能:
calctvd :: [Perk] -> [Perk] -> Perk -> Double
calctvd ps fs p = (fromIntegral(tvn) / fromIntegral(points)) :: Double
where
tvn = calctvn ps fs p
points = length $ [i | i <- perkAndPreqs ps p, i `notElem` fs]
以上功能总是成功返回我期望的双倍。重要的是划分(fromIntegral(tvn) / fromIntegral(points))
。函数calctvn(此处未显示)和变量点总是整数,因此fromIntegral()是必需的。
updatetvd :: [Perk] -> [Perk] -> [Perk]
updatetvd [] _ = []
updatetvd ps fs
--If p is in the list of elements already taken, then do not update it
| p `elem` fs = [p] ++ updatetvd (tail ps) fs
--Otherwise, update the tvd value
| otherwise = [PerkImpl (tvd, school, skill, name, def, preqstr, pref)] ++ updatetvd (tail ps) fs
where
p = head ps
PerkImpl (_, school, skill, name, def, preqstr, pref) = p
tvd = calctvd ps fs p
基本上,第二个函数应该只将第一个函数的值插入到列表中。但是,它只插入术语(fromIntegral(tvn) / fromIntegral(points))
的分子。我通过将calctvd中的那一行更改为3 / fromIntegral(points)
来证明这一点。有了这个,calctvd仍然返回正确分割的双,而updatetvd总是插入值3.0。如果从updatetvd内部调用calctvd,就好像Haskell不评估分母。
更新1:
然而,似乎这种奇怪性依赖于上述两个函数的某些复杂性。我试图把它分解成一个简单的例子:
testcalctvd :: Double
testcalctvd = fromIntegral(3) / fromIntegral(4) :: Double
testupdatetvd :: Double
testupdatetvd = testcalctvd
但是,testcalctvd和testupdatetvd都返回正确的0.75。
更新2:
这是一个直接来自终端的示例,使用测试术语3 / fromIntegral(points)
:
> calctvd initial [] i17
0.6 {This is 3/5, because i17 has 5 points}
> updatetvd initial []
[...3.0...] {This is just the numerator 3}
更新3:
这是perkAndPreqs函数,这可能是罪魁祸首,但我不确定它会有多大意义:
--Take a perk and return a list of that perk and all of its pre-requisites
perkAndPreqs :: [Perk] -> Perk -> [Perk]
perkAndPreqs _ NULL = []
perkAndPreqs ps p = [p] ++ perkAndPreqs ps preq
where
PerkImpl (_, _, _, _, _, preqstring, _) = p
preq = perkIdentifier preqstring ps
答案 0 :(得分:1)
我的猜测是,当您手动调用calctvd
时,您传递的p
参数也不是ps
参数的第一个元素。但是从calctvd
,updatetvd
调用p = head ps
时。
我无法确定,因为您向我们展示了既没有测试案例失败也没有perkAndPreqs
的定义(如果points
被误算为1
,那么为什么是可能在perkAndPreqs
)。