我已经定义了以下功能:
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?或者我在这里忽略了一个完全愚蠢的错误?
答案 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
只使用列表中的go
和n-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/x
自r :: 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)
解决问题的方法是将a
和r
的类型从Int
更改为Double
。