Страницы

Поиск по вопросам

пятница, 5 октября 2018 г.

Haskell аппликативный или нормальный?

Я изучаю язык Haskell и параллельно читаю SICP. В SICP нашёл следующее. Бен Битобор (согласно книге SICP) придумал тест для проверки интерпретатора на то, с каким порядком вычислений он работает, аппликативным или нормальным. Бен определяет такие две процедуры:
(define (p) (p)) (define (test x y) (if (= x 0) 0 y))
Затем он вычисляет выражение:
(test 0 (p))
Если результатом является 0, то интерпретатор - нормальный, если впадает в вычисление "p" - аппликативный. Согласно теста язык Scheme является аппликативным. Я переписал проверку под Haskell для интерпретатора GHCi:
let p = p let test x y = if (x == 0) then 0 else y test 0 p
Результатом получил 0. Правильно ли я применил тест Битобора, результатом которого является факт, что Haskell (GHCi) является нормальным языком программирования? Равносильно ли это понятию "ленивые вычисления"?


Ответ

Всё правильно
Да, Haskell в терминах этой книги нормальный
...и речь действительно идёт о ленивых вычислениях, а именно ленивом вычислении аргументов функции при её вызове. Термина нормальный стоит в этом контексте избегать ввиду его излишней общности и распространённости в самых разных областях, термин ленивый куда осмысленнее.
Первая процедура — очевидная "рекурсивная бомба", которая вешает выполнение программы при попытке вызова (если нет оптимизации хвостовой рекурсии, то ещё и уронит программу). Поэтому весь тест упирается в то, будет ли вычислен второй аргумент независимо от того, потребует ли его значения функция в процессе выполнения.
Внимание стоит обратить лишь на ту деталь, что нельзя просто так выкинуть вторую процедуру и заинлайнить её вызов в её реализации как-то так:
(if (= 0 0) 0 (p))
...потому что if в лиспах обычно является особой формой (special form), а не функцией, а потому имеет другой порядок вычислений, чем для вызовов функций.

Комментариев нет:

Отправить комментарий