Как преобразовать программу Scheme в Haskell? - PullRequest
2 голосов
/ 09 ноября 2010

Я собираюсь преобразовать программу-схему в Haskell, но мне сложно узнать все о Haskell.Если вы знакомы с SICP, мне предлагается ответить на Упражнения 3.63, 3.64, 3.65, 3.66 и 3.71.Я уже нашел ответы на эти проблемы, но они написаны на схеме.Вот вопрос и ответ в 3.63:

Упражнение 3.63.Луис Ризонер спрашивает, почему процедура sqrt-stream не была написана следующим более простым способом, без предположений о локальной переменной:

(define (sqrt-stream x)
  (cons-stream 1.0
  (stream-map (lambda (guess)
  (sqrt-improve guess x))
    (sqrt-stream x))))

Алисса П. Хакер отвечает, что эта версия процедуры значительно менее эффективна, посколькуон выполняет избыточные вычисления.

Объясните ответ Алиссы.

Будут ли две версии по-прежнему отличаться по эффективности, если наша реализация задержки будет использовать только (lambda () <exp>) без использования оптимизации, предоставляемой memo-proc (раздел 3.5.1)?

Ответ:

В процедуре Луи Ризонера (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

Пожалуйста, помогите мне исправить мои коды.Они понадобятся мне на следующей неделе.

Я также попробую другие и опубликую их здесь, если там снова будут ошибки.Надеюсь, что вы можете мне помочь. Большое спасибо.

1 Ответ

2 голосов
/ 09 ноября 2010

Ваш код на Haskell выглядит неправильно на многих уровнях (например, do не является циклической конструкцией, вы не можете назначить новое значение для угадывания). Я могу только догадываться, что вы хотите. Вот функция, вычисляющая квадратный корень:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...