Haskell возвращает только числитель подразделения (иногда) - PullRequest
0 голосов
/ 21 ноября 2011

У меня есть две функции:

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 по-прежнему возвращал правильно разделенный double, тогда как updatetvd всегда вставлял значение 3.0.Как будто Хаскелл не вычисляет знаменатель, если calctvd вызывается изнутри updatetvd.

Обновление 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 Ответ

1 голос
/ 21 ноября 2011

Я предполагаю, что когда вы вызываете calctvd вручную, передаваемый вами параметр p также не является первым элементом параметра ps.Но когда calctvd вызывается из updatetvd, p = head ps.

, я не могу быть уверен, потому что вы не показали нам ни неудачных тестов, ни определения perkAndPreqs (если pointsошибочно рассчитанный как 1, ключ к пониманию того, почему он может быть в perkAndPreqs).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...