Haskell仅返回除法的分子(有时)

时间:2011-11-21 00:14:42

标签: math haskell

我有两个功能:

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

1 个答案:

答案 0 :(得分:1)

我的猜测是,当您手动调用calctvd时,您传递的p参数也不是ps参数的第一个元素。但是从calctvdupdatetvd调用p = head ps时。

我无法确定,因为您向我们展示了既没有测试案例失败也没有perkAndPreqs的定义(如果points被误算为1,那么为什么是可能在perkAndPreqs)。