我要将一个方案程序转换为Haskell,但我很难学习Haskell的所有内容。如果您熟悉SICP,我的任务是回答练习3.63,3.64,3.65,3.66和3.71。我已经找到了这些问题的答案,但它们是用方案编写的。以下是3.63中的问题和答案:
练习3.63。 Louis Reasoner问为什么sqrt-stream过程不是以下面更直接的方式编写的,没有局部变量猜测:
(define (sqrt-stream x) (cons-stream 1.0 (stream-map (lambda (guess) (sqrt-improve guess x)) (sqrt-stream x))))
Alyssa P. Hacker回复说,这个版本的程序效率低得多,因为它执行冗余计算。
解释Alyssa的回答。
如果我们的延迟实现仅使用
(lambda () <exp>)
而不使用memo-proc(第3.5.1节)提供的优化,那么这两个版本的效率是否会有所不同?
答案:
在Louis Reasoner的程序中,在
(sqrt-stream x)
内递归调用(sqrt-stream x)
。但是,这两个流不是同一个变量。因此,执行冗余计算。在原始版本中,使用局部变量猜测。(define (sqrt-stream x) (define guesses (cons-stream 1.0 (stream-map (lambda (guess) (sqrt-improve guess x)) guesses))) guesses) (display-stream (sqrt-stream 2))
这是我写的Haskell代码,它不起作用:
module Main
where
guess = 1:: Double
x=0
do
if ((guess*guess) = x)
then y = (x + guess) / x
guess = y
else
sqrt x = guess
请帮我修改我的代码。我下周需要它们。
我还会尝试其他的并在此处发布,如果再次出现错误的话。希望你能帮帮我。谢谢。
答案 0 :(得分:2)
您的Haskell代码在如此多的级别上看起来是错误的(例如,没有循环结构,您无法分配新的值来猜测)。我只能猜到你想要的东西。这是一个计算平方根的函数:
sqrt' :: Double -> Double
sqrt' n = loop n
where loop guess | abs (guess - improve guess) < 0.00000000001 = improve guess
| otherwise = loop $ improve guess
improve guess = 0.5 * (guess + n / guess)
这是一个版本,它为您提供近似值列表(直到它不再改变):
sqrt' :: Double -> [Double]
sqrt' n = takeChanging $ iterate (\ guess -> 0.5 * (guess + n / guess)) n
where takeChanging (x:y:ys) | abs (x-y) < 0.00000000001 = [x]
| otherwise = x : takeChanging (y:ys)