Haskell - 期望的类型与实际类型

时间:2013-12-04 08:59:50

标签: haskell types

我已经定义了以下功能:

calculateApproximation :: Int -> Int -> Int -> Double -> Double
calculateApproximation n a r tol =
  if abs(((take n xs)!!(n-1)) - (((take n xs)!!(n-2)))) <= tol
    then ((take n xs)!!(n-1))
    else calculateApproximation (n+1) a r tol
  where xs = unfoldr (\x -> Just(x, (x + (r/x))/2)) a

但我看到以下类型错误:

Couldn't match expected type `Int' with actual type `Double'
    In the second argument of `(<=)', namely `tol'
    In the expression:
      abs (((take n xs) !! (n - 1)) - (((take n xs) !! (n - 2)))) <= tol

但是,当我已经将它定义为Double时,为什么期望tol成为Int?或者我在这里忽略了一个完全愚蠢的错误?

4 个答案:

答案 0 :(得分:6)

最简单的解决方法是修改类型签名,以便您的初始猜测a和计算平方根r的数字是Double而不是{{1} }}

我也冒昧地将定义Int分解出来以简化代码。

ys = take n xs

但是,正如评论中指出的那样,在查找calculateApproximation :: Int -> Double -> Double -> Double -> Double calculateApproximation n a r tol = if abs (ys!!(n-1) - ys!!(n-2)) <= tol then ys!!(n-1) else calculateApproximation (n+1) a r tol where xs = unfoldr (\x -> Just(x, (x + (r/x))/2)) a ys = take n xs 元素之前,您实际上不需要采用n元素。您可以将n-1应用于无限列表,这会进一步简化您的代码

!!

为了清晰起见,我可能会考虑更多的定义,给出

calculateApproximation :: Int -> Double -> Double -> Double -> Double
calculateApproximation n a r tol =
    if abs (xs!!(n-1) - xs!!(n-2)) <= tol
        then xs!!(n-1)
        else calculateApproximation (n+1) a r tol
    where xs = unfoldr (\x -> Just(x, (x + (r/x))/2)) a

最后,我会注意到操作calculateApproximation' n a r tol = go n where go n = let eps = abs $ xs!!(n-1) - xs!!(n-2) in if eps <= tol then xs !! (n-1) else go (n+1) xs = unfoldr (\x -> Just (x, (x + r/x)/2)) a 只使用列表中的gon-1元素,而不是之前的元素,以及索引n-2仅用于跟踪列表中的位置。所以我会重写,以便n在列表上运行,而不是在索引上运行,并让它遍历列表,直到找到合适的答案。在一个小小的整理过程中,我会从go更改为unfoldr - 如果列表应该在某个时间点终止,您只需要iterate

unfoldr

答案 1 :(得分:4)

“实际”是指tol签名中Double的{​​{1}}类型。

“预期”是指calculate必须是tol才能在Int的右侧有意义,左侧已经是<=

答案 2 :(得分:1)

如果您希望xs具有Double类型,则unfoldr中的匿名函数类型必须为a -> Just (a, Double)。如果该对的第二部分涉及与您的定义中的总和相似的总和,那么您可能希望a也是Double。最后,r/xr :: Int以来没有意义,所以你想要

xs = unfoldr (\x -> Just(x, (x + ((fromIntegral r)/x))/2)) (fromIntegral a).

(我觉得肯定有更短/更清晰的方式来写这个。你可能想要考虑一下 - 或者看看Chris Taylor的答案。)

PS:另见Aadit M Shah关于摆脱take的评论。

答案 3 :(得分:1)

这就是我编写代码的方式:

import Data.List

calculateApproximation :: Double -> Double -> Double -> Int -> Double
calculateApproximation a r tol = getApproximation
    where xs = unfoldr (\x -> Just (x, (x + r / x) / 2)) a
          getApproximation n = if abs (x - xs !! (n - 2)) <= tol
                                   then x else getApproximation (n + 1)
              where x = xs !! (n - 2)

解决问题的方法是将ar的类型从Int更改为Double