2016-03-05 2 views
1

Давайте посмотрим, анализировать код для факториала в Haskell, используя функцию лямбда:Рекурсивные лямбда в Haskell

y f x = f (y f) x 

factorial = y (\t n -> if n == 1 then 1 else n * t(n-1)) 

И я не могу понять, как это работает. Я знаю, что это связано с исчислением лямбда, но в настоящее время я не знаком с этим, поэтому я должен понимать без него или с минимальными знаниями. Мое сомнение есть: Что такое f в определении factorial? Я имею в виду это f: y f x = f (y f) x.

Итак, что здесь? y (\ t n -> if n == 1 then 1 else n * t (n-1))

Пожалуйста, объясните мне, что, возможно, рекурсия?

+0

Обратите внимание, что сама лямбда не является рекурсивной; он просто принимает функцию, которая применяется к 'n - 1'. – chepner

+0

Да, я вижу. : D – Gilgamesz

ответ

5

f в factorial является (\t n -> if n == 1 ...)лямбда

y является так называемая fix-point combinator и используется для того, чтобы рекурсивные определения в лямбда-исчислении (это относится f к, это аргумент снова и снова рекурсивно)

, чтобы понять, как это работает, вы можете просто сделать некоторые оценки вручную:

factorial 3 
= y (\t n -> ...) 3 
{ def y and y (\t n -> ...) = factorial by eta-red. } 
= (\t n -> ...) factorial 3 
{ t = factorial, n = 3 -> else case } 
= 3 * factorial 2 
= 3 * (y (\t n -> ...) 2) 
= 3 * ((\t n -> ...) factorial 2) 
= { t = factorial, n = 2 -> else case } 
= 3 * (2 * factorial 1) 
= 3 * (2 * (y (\t n -> ...) 1)) 
= 3 * (2 * ((\t n -> ...) factorial 1))) 
{ t = factorial n = 1 -> then case } 
= 3 * (2 * 1) 
= 6 
+0

Хорошо, я сомневаюсь в этом: t (n-1). t - наша лямбда-функция. t (lambda) получает TWO аргументы, пока мы приводим один аргумент (n -1). Мое предположение - это то, что связано с ленимией Хаскелла? Не могли бы вы объяснить мне это более подробно? Если вы предлагаете, я создам новый объект, – Gilgamesz

+1

Нет 't' имеет только один аргумент, и если вы внимательно посмотрите, мы будем называть его только одним - лямбда-часть - это' \ tn -> ... '- see эта (неназванная) функция принимает два аргумента: один - 't', а другой -' n' - это сложная часть сгибания ума, так как это позволяет нам определять рекурсивную комбинацию с комбинатором 'y'-fix point – Carsten

+0

It it вызвано тем, что рекурсия будет бесконечно (останавливать ограничение) расширенной, и нет места для аргумента t. Я прав? – Gilgamesz

1

y - fixed-point combinator, также известный как y-combinator. В

factorial = y (\t n -> if n == 1 then 1 else n * t(n-1)) 

лямбда (\t n -> if n == 1 then 1 else n * t(n-1)) обязан f в определении y. Вы можете сделать расширение:

(\t n -> if n == 1 then 1 else n * t(n-1)) (y (\t n -> if n == 1 then 1 else n * t(n-1))) 

так внутри лямбда, t будет связано с самой лямбды, что позволяет ему называть себя рекурсивно.

0

Возможно, это легче, если вы выписывать у комбинатор, таким образом, с двумя ETA-расширений:

y :: ((a->b) -> a->b) -> a->b 
y f x a = f (\q a' -> y f q a') x a 

Так f в основном получает рекурсивный вызов (с a' вместо a) в качестве первого аргумента ,

Смежные вопросы