#haskell #lazy-evaluation #evaluation #fixpoint-combinators
#хаскелл #ленивая оценка #оценка #фиксированная точка-комбинаторы
Вопрос:
fix f = let {x = f x} in x
Говоря о let
, я подумал, что let P = Q in R
это будет оценивать Q -> Q’, тогда P заменяется на Q’ в R, или: R[P -> Q']
.
Но в fix
определении Q зависит от R, как тогда оценить?
Я предполагаю, что речь идет о ленивой оценке. Q’ становится грохотом, но я не могу рассуждать об этом в своей голове.
Исходя из контекста, я смотрю на Y combinator, он должен найти фиксированную точку функции, поэтому, если у меня есть эта функция, one x = 1
, то fix one == 1
она должна выполняться, верно?
Так fix one = let {x = one x} in x
что, но я не вижу, как 1
из этого можно было бы выйти.
Ответ №1:
Говоря о let, я подумал, что let
P = Q in R
будет вычислятьсяQ -> Q'
, а затемP
заменяется наQ'
inR
, или:R[P -> Q']
.
Морально, да, но P
оценивается не сразу, оно оценивается при необходимости.
Но в каком определении
Q
это зависит отR
того, как тогда оценивать?
Q
не зависит от R
, это зависит от P
. Это P
рекурсивно зависит от самого себя. Это может привести к нескольким различным результатам. Грубо говоря:
- Если
Q
не может вернуть какую-либо часть своего результата перед вычислениемP
, тоP
представляет собой бесконечно повторяющееся вычисление, которое не завершается. Например,let x = x 1 in x -- loops forever with no result -- (GHC is able to catch this specific case and raise an exception instead, -- but it's an irrelevant detail)
- Если
Q
вместо этого может вернуть часть своего результата перед необходимостью оценкиP
, он это делает.let x = 2 : x in x -- x = 2 : .... can be generated immediately -- This results in the infinite list 2:2:2:2:2:..... let x = (32, 10 fst x) in x -- x = (32, ...) can be generated immediately -- hence x = (32, 10 fst (32, ...)) = (32, 10 32) = (32, 42)
Я полагаю, что речь идет о ленивой оценке.
Q'
становится проблемой, но я не могу рассуждать об этом в своей голове.
P
связано с ударом. Важно то, вызывает ли этот блок сам себя, прежде чем возвращать какую-то часть вывода или нет.
Исходя из контекста, я смотрю на Y combinator, он должен найти фиксированную точку функции, поэтому, если у меня есть эта функция.
one x = 1
, тогдаfix one == 1
должно выполняться, верно?
ДА.
Итак
fix one = let x = one x in x
, но я не понимаю, почему1
из этого следует
Мы можем вычислить это следующим образом:
fix one
= {- definition of fix -}
let x = one x in x
= {- definition of x -}
let x = one x in one x
= {- definition of one -}
let x = one x in 1
= {- x is now irrelevant -}
1
Просто расширьте определения. Сохраняйте рекурсивные определения на случай, если они вам понадобятся снова.
Комментарии:
1. Потрясающе, большое вам спасибо,. Это было уравнительное рассуждение? Мне нужно практиковать это
2. @geckos Да, это уравнительное рассуждение. Имейте в виду, что GHC может не точно следовать этим шагам (его система выполнения довольно сложная, с использованием тонны оптимизаций), но она гарантированно приведет к тому же результату.
3. (Я слишком поспешил опубликовать свой ответ, прежде чем увидеть окончание вашего сообщения … :))
4. @гекконы Да. Чтобы быть педантичным, я бы сказал, что
f x
это зависит отx
, а не от того, чтоf
зависит отx
. Вы говорите последнее только потому, что знаете, чтоf
к нему применяетсяx
, поэтому вы упоминаетеf
, но вы думаетеf x
.5. @geckos Это рекурсивное определение, поэтому вы используете его до того, как оно будет полностью определено. В императивных процедурных языках вы можете написать функцию
def x(): if ... then use x() else ...
, которая вызывает саму себя. В Haskell вы можете сделать это даже для не-функций (потому что Haskell ленив).