什么是Y-组合?[关闭]
-
01-07-2019 - |
题
Y组合是一个计算机科学的概念从"职能"方面的事情。大多数程序员不知道很多有关的组合器,如果他们甚至已经听取了关于他们。
- 什么是Y-组合?
- 如何组合子的工作?
- 它们是什么好处?
- 他们是有用的,在程序性的语言?
解决方案
如果你准备好了只要阅读, 迈克*凡尼尔有一个 伟大的 解释.长话短说,它可以让你实现递归的语言,这并不一定支持它本身。
其他提示
Y组合是一种"功能性"(功能操作的其他职能),使递归的时候你可以不参阅的职能从内的本身。在计算机科学的理论, 概括递归,抽象其实施,并由此脱离实际工作的职能中的问题。的利益,不需要编译时间名字递归功能是一种奖励。=)
这是可适用的语言支持 lambda功能.的 表达基于性lambda通常意味着它们不能引用自己的姓名。和周围的工作,这通过的声明的变量,为参照,然后分配lambda,以完成自参循环,为脆弱。Lambda变量可以复制的,与原始变量重新分配,这会破坏自参考。
Y组合子是繁琐的实施,并经常使用, 静态型 语言(它 程序性语言 往往正),因为通常的打字的限制,需要参数的数量的功能,在问题是在编译时间。这意味着,一个y组合必须是书面的任何论点数,其中一个需要使用。
下面是一个如何使用和工作的Y-组合,在C#。
使用Y组合涉及一个"异常"的方式构建一个递归功能。首先,你必须写你的功能作一段代码,电话预先存在的功能,而不是本身:
// Factorial, if func does the same thing as this bit of code...
x == 0 ? 1: x * func(x - 1);
然后你把这一成功,需要一个功能调和返回的一个函数,这样做。这就是所谓的功能,因为它需要一个功能,并执行一个运作,结果在另一个功能。
// A function that creates a factorial, but only if you pass in
// a function that does what the inner function is doing.
Func<Func<Double, Double>, Func<Double, Double>> fact =
(recurs) =>
(x) =>
x == 0 ? 1 : x * recurs(x - 1);
现在你有一个函数的一个函数,以及返回的另一个功能,这种看起来像一个因子,而是自称,它要求参数通过进入外层的功能。你怎么让这个因子?通过内部职能本身。Y组合并,由一个功能与永久性的名字,这可以介绍递归。
// One-argument Y-Combinator.
public static Func<T, TResult> Y<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> F)
{
return
t => // A function that...
F( // Calls the factorial creator, passing in...
Y(F) // The result of this same Y-combinator function call...
// (Here is where the recursion is introduced.)
)
(t); // And passes the argument into the work function.
}
而不是因子叫本身,会发生什么情况是,因话的因子生成器(返回通过递归呼吁Y组合).并且取决于当前的t值的功能返回从发电机将呼叫的再次发生器,t-1,或者只是返回1,终止递归。
它是复杂的和神秘,但它的所有动摇在运行时,关键工作是"推迟执行",并破坏的递归,跨越两个功能。内F 通过作为一个参数, 称在下一次迭代, 只有如果有必要.
我已经解除这种从 http://www.mail-archive.com/boston-pm@mail.pm.org/msg02716.html 这是一个解释我写了几年前。
我会用JavaScript在这个例子中,但许多其他语言的工作。
我们的目标是能够编写递归功能的1 变量使用的唯一职能的1个变量并没有 工作分配,确定名字的东西,等等。(为什么这是我们的 目标是另外一个问题,我们只是把此作为 挑战,我们正在给定。) 似乎是不可能的,对吧?作为 一个例子,让我们实现的因素。
好步骤1是说,我们可以很容易地做到这一点,如果我们 欺骗一点。使用功能的变量和2 分配我们至少可以避免使用 分配给设立的递归。
// Here's the function that we want to recurse.
X = function (recurse, n) {
if (0 == n)
return 1;
else
return n * recurse(recurse, n - 1);
};
// This will get X to recurse.
Y = function (builder, n) {
return builder(builder, n);
};
// Here it is in action.
Y(
X,
5
);
现在让我们来看看如果我们可以欺骗下。好的首先我们使用 分配,但我们不需要。我们只能写和X Y内联。
// No assignment this time.
function (builder, n) {
return builder(builder, n);
}(
function (recurse, n) {
if (0 == n)
return 1;
else
return n * recurse(recurse, n - 1);
},
5
);
但是,我们正在使用功能的2个变量,以获得一个函数的1 变量。我们能解决吗?好了聪明的家伙的名字 Haskell咖喱有一个绝招,如果你有好高了 功能,那么你只需要职能的1个变量。的 证明是,你可以从职能的2个(或多个的 一般情况)的变量为1变量有一个纯粹的 机械的文本转变这样的:
// Original
F = function (i, j) {
...
};
F(i,j);
// Transformed
F = function (i) { return function (j) {
...
}};
F(i)(j);
在哪里...仍然完全相同。(这一招呼 "柯里化"之后,它的发明者。语言Haskell也是 命名为Haskell咖喱。文件下无益的琐事。) 现在只适用于这种转变无处不在,我们得到 我们的最终版本。
// The dreaded Y-combinator in action!
function (builder) { return function (n) {
return builder(builder)(n);
}}(
function (recurse) { return function (n) {
if (0 == n)
return 1;
else
return n * recurse(recurse)(n - 1);
}})(
5
);
随意尝试它。警报()就返回,把它绑在一个按钮什么的。这代码计算阶乘,递归的,而无需使用 分配、声明、或职能2的变量。(但是 试图追踪它是如何工作的可能让你晕头转.和移交,而不导,只要稍微重新格式化 将会导致的代码一定要挡板和混淆。)
你可以替代的4行,递归的定义因素与 任何其他递归功能。
我不知道如果有任何使用在试图建立这个从地上爬起来。让我们来看看。这是一个基本的,递归因素的功能:
function factorial(n) {
return n == 0 ? 1 : n * factorial(n - 1);
}
让我们重构和创建一个新的功能叫 fact
返回匿名因子计算功能,而不是执行的计算:
function fact() {
return function(n) {
return n == 0 ? 1 : n * fact()(n - 1);
};
}
var factorial = fact();
那是有点怪异,但没有什么是错误的。我们只是产生一个新的因素的功能,在每个步骤。
递归在这一阶段仍然是相当明确的。的 fact
功能需要了解其自己的名字。让我们参数化的递归的呼吁:
function fact(recurse) {
return function(n) {
return n == 0 ? 1 : n * recurse(n - 1);
};
}
function recurser(x) {
return fact(recurser)(x);
}
var factorial = fact(recurser);
这是伟大的,但 recurser
仍然需要知道自己的名称。让我们参数化,也:
function recurser(f) {
return fact(function(x) {
return f(f)(x);
});
}
var factorial = recurser(recurser);
现在,而不是呼叫 recurser(recurser)
直接,让我们创建一个包装的功能返回其结果是:
function Y() {
return (function(f) {
return f(f);
})(recurser);
}
var factorial = Y();
我们现在可以摆脱的 recurser
名字完全;它只是一个参数之内的功能,这可以被替换的功能,本身:
function Y() {
return (function(f) {
return f(f);
})(function(f) {
return fact(function(x) {
return f(f)(x);
});
});
}
var factorial = Y();
唯一的外部名称仍然是引用 fact
, 但应该清楚现在,这是很容易的参数化,也创造完成后,通用的解决方案:
function Y(le) {
return (function(f) {
return f(f);
})(function(f) {
return le(function(x) {
return f(f)(x);
});
});
}
var factorial = Y(function(recurse) {
return function(n) {
return n == 0 ? 1 : n * recurse(n - 1);
};
});
y在组合 JavaScript:
var Y = function(f) {
return (function(g) {
return g(g);
})(function(h) {
return function() {
return f(h(h)).apply(null, arguments);
};
});
};
var factorial = Y(function(recurse) {
return function(x) {
return x == 0 ? 1 : x * recurse(x-1);
};
});
factorial(5) // -> 120
编辑:我学习了很多看码,但是这一次是有点难以下咽,没有一些背景-对不起有一些一般性的知识提出的其他答复,您可以开始挑选除了发生了什么。
Y功能的"y-组合".现在看看 var factorial
行Y是用。注意到你传递一个函数,有一个参数(在这个例子中, recurse
),还用于后来在内的功能。参名称基本上变成了名的内的功能允许其执行递归呼吁(因为它使用 recurse()
在它的定义。) Y组合进行的魔法的关联,否则匿名内部的功能与参名称的功能传递给Y。
为充分解释如何Y没有魔法,检查了 链接的文章 (不由我顺便说一句.)
为程序员,他们还没有遇到编程功能在深度,以及不管现在开始,但被客气一点好奇:
该Y组合是一个公式,它可以让你实现递归在一个情况下,职能不能有名字,但是可以通过周围的参数,用作回值,并定义内的其他功能。
它的工作通过的功能本身作为一个参数,所以它可以叫本身。
它的一部分氧微积分,这是真的,数学,但实际上是一种编程语言,并且是非常基本的计算机科学和尤其是功能性的程序。
一天一天的实用价值的Y组合是有限的,因为编程语言倾向于让你名字的功能。
在情况需要确定它在警方的阵容,它看起来像这样:
Y=λf.(λx.f(x))(λx.f(x))
你通常可以发现它,因为重复 (λx.f (x x))
.
的 λ
符号是希腊字母lambda,这给lambda演算将其名称,并且有很多 (λx.t)
风格的条款,因为这是氧微积分的外观。
其他的答案提供相当简明扼要的答案,而不的一个重要的事实:你不需要实施定点组合中的任何实际的语言这种令人费解的方式,这样做没有任何实际的目的(除了"你看,我知道Y组合是")。这是重要的理论概念,但很少实际价值。
这里是一个JavaScript执行Y组合和因素的功能(从道格拉斯Crockford的文可在: http://javascript.crockford.com/little.html).
function Y(le) {
return (function (f) {
return f(f);
}(function (f) {
return le(function (x) {
return f(f)(x);
});
}));
}
var factorial = Y(function (fac) {
return function (n) {
return n <= 2 ? n : n * fac(n - 1);
};
});
var number120 = factorial(5);
Y组合是另一个名称为通量电容器。
我已经写入了一种"白痴的指南"Y-组合中既有质量的技术资源和方案,以便帮助自己来掌握它。他们有影响的材料"的小阴谋家"
在方案:https://gist.github.com/z5h/238891
或题:https://gist.github.com/z5h/5102747
这两个教程码穿插的意见,并应削减和pastable到你喜欢编辑器。
匿名递归
一个定点的组合是一个高级功能 fix
通过定义满足的等同性
forall f. fix f = f (fix f)
fix f
代表一个解决方案 x
到定点公式
x = f x
因子的一个自然人数可以证明
fact 0 = 1
fact n = n * fact (n - 1)
使用 fix
, 任意建设性的证据一般/μ递归功能,可得出不nonymous自referentiality.
fact n = (fix fact') n
哪里
fact' rec n = if n == 0
then 1
else n * rec (n - 1)
这样,
fact 3
= (fix fact') 3
= fact' (fix fact') 3
= if 3 == 0 then 1 else 3 * (fix fact') (3 - 1)
= 3 * (fix fact') 2
= 3 * fact' (fix fact') 2
= 3 * if 2 == 0 then 1 else 2 * (fix fact') (2 - 1)
= 3 * 2 * (fix fact') 1
= 3 * 2 * fact' (fix fact') 1
= 3 * 2 * if 1 == 0 then 1 else 1 * (fix fact') (1 - 1)
= 3 * 2 * 1 * (fix fact') 0
= 3 * 2 * 1 * fact' (fix fact') 0
= 3 * 2 * 1 * if 0 == 0 then 1 else 0 * (fix fact') (0 - 1)
= 3 * 2 * 1 * 1
= 6
这一正式证据,证明
fact 3 = 6
有条不紊地使用定点组合等同于 重写
fix fact' -> fact' (fix fact')
氧微积分
的 无类型的氧微积分 形式主义,包括在一个方面。
E ::= v Variable
| λ v. E Abstraction
| E E Application
哪里 v
范围上的变量,同 beta 和 eta减少 规则
(λ x. B) E -> B[x := E] Beta
λ x. E x -> E if x doesn’t occur free in E Eta
测试替代品减少所有自由发生的变量 x
在抽象("功能")的身体 B
由的表达("argument") E
.Eta减少消除了多余的抽象概念。它有时是省略了形式主义。一个 束缚 表达,这没有减少规则的适用,是在 正常的 或 规范的形式.
λ x y. E
是的缩写
λ x. λ y. E
(抽象multiarity),
E F G
是的缩写
(E F) G
(应用左关联性),
λ x. x
和
λ y. y
都 alpha-等同.
抽象和应用的是两只有"用语的原语"lambda微积分,但它们允许 编码 随意复杂的数据和操作。
教会数字编码的自然数字相似皮亚诺-不言自明的土黄。
0 = λ f x. x No application
1 = λ f x. f x One application
2 = λ f x. f (f x) Twofold
3 = λ f x. f (f (f x)) Threefold
. . .
SUCC = λ n f x. f (n f x) Successor
ADD = λ n m f x. n f (m f x) Addition
MULT = λ n m f x. n (m f) x Multiplication
. . .
一个正式的证明
1 + 2 = 3
使用重写规则的减少:
ADD 1 2
= (λ n m f x. n f (m f x)) (λ g y. g y) (λ h z. h (h z))
= (λ m f x. (λ g y. g y) f (m f x)) (λ h z. h (h z))
= (λ m f x. (λ y. f y) (m f x)) (λ h z. h (h z))
= (λ m f x. f (m f x)) (λ h z. h (h z))
= λ f x. f ((λ h z. h (h z)) f x)
= λ f x. f ((λ z. f (f z)) x)
= λ f x. f (f (f x)) Normal form
= 3
组合子
在氧微积分 组合子 是抽象概念,包含下没有免费的变量。最简单: I
, 身份组合
λ x. x
同构的身份的功能
id x = x
这种组合子是原始经营者 组合的结石 喜欢滑雪系统。
S = λ x y z. x z (y z)
K = λ x y. x
I = λ x. x
Beta减少不是 强烈正常化;不是所有的还原性的表达,"redexes",收敛到正常的形式下测试减少。一个简单的例子是不同的应用程序的欧米茄 ω
组合
λ x. x x
到本身:
(λ x. x x) (λ y. y y)
= (λ y. y y) (λ y. y y)
. . .
= _|_ Bottom
减少的最左子表达式("头")是优先考虑。 应用了 恢复正常的参数之前替换, 正常秩序 不。两个战略都类似于急切的评估,例如C,和懒惰的评价,例如Haskell.
K (I a) (ω ω)
= (λ k l. k) ((λ i. i) a) ((λ x. x x) (λ y. y y))
发散下的渴望应用阶测试减少
= (λ k l. k) a ((λ x. x x) (λ y. y y))
= (λ l. a) ((λ x. x x) (λ y. y y))
= (λ l. a) ((λ y. y y) (λ y. y y))
. . .
= _|_
由于在 严格 语义
forall f. f _|_ = _|_
但是收敛下懒正常-以减少测试
= (λ l. ((λ i. i) a)) ((λ x. x x) (λ y. y y))
= (λ l. a) ((λ x. x x) (λ y. y y))
= a
如果一个表达有一个正常的形式,正常-以测试减少会找到它。
Y
重要的财产 Y
定点组合
λ f. (λ x. f (x x)) (λ x. f (x x))
是给予
Y g
= (λ f. (λ x. f (x x)) (λ x. f (x x))) g
= (λ x. g (x x)) (λ x. g (x x)) = Y g
= g ((λ x. g (x x)) (λ x. g (x x))) = g (Y g)
= g (g ((λ x. g (x x)) (λ x. g (x x)))) = g (g (Y g))
. . . . . .
等价
Y g = g (Y g)
是同构
fix f = f (fix f)
的类型氧微积分可以进行编码任意建设性的证据一般/μ递归功能。
FACT = λ n. Y FACT' n
FACT' = λ rec n. if n == 0 then 1 else n * rec (n - 1)
FACT 3
= (λ n. Y FACT' n) 3
= Y FACT' 3
= FACT' (Y FACT') 3
= if 3 == 0 then 1 else 3 * (Y FACT') (3 - 1)
= 3 * (Y FACT') (3 - 1)
= 3 * FACT' (Y FACT') 2
= 3 * if 2 == 0 then 1 else 2 * (Y FACT') (2 - 1)
= 3 * 2 * (Y FACT') 1
= 3 * 2 * FACT' (Y FACT') 1
= 3 * 2 * if 1 == 0 then 1 else 1 * (Y FACT') (1 - 1)
= 3 * 2 * 1 * (Y FACT') 0
= 3 * 2 * 1 * FACT' (Y FACT') 0
= 3 * 2 * 1 * if 0 == 0 then 1 else 0 * (Y FACT') (0 - 1)
= 3 * 2 * 1 * 1
= 6
(乘延迟交汇处)
为Churchian类型氧微积分,那里已经显示出存在一种递归的。无限的固定点的组合器除了 Y
.
X = λ f. (λ x. x x) (λ x. f (x x))
Y' = (λ x y. x y x) (λ y x. y (x y x))
Z = λ f. (λ x. f (λ v. x x v)) (λ x. f (λ v. x x v))
Θ = (λ x y. y (x x y)) (λ x y. y (x x y))
. . .
正了测试减少使未扩展类型氧微积分图灵-完全重写系统。
在Haskell,定点组合可以是优雅的实施
fix :: forall t. (t -> t) -> t
fix f = f (fix f)
Haskell的懒惰恢复正常的一个菲堤前所有子表达式已经进行评价。
primes :: Integral t => [t]
primes = sieve [2 ..]
where
sieve = fix (\ rec (p : ns) ->
p : rec [n | n <- ns
, n `rem` p /= 0])
- 大卫*特纳: 教会的理论和编程功能
- 阿朗佐的教堂: 一个无法解决的问题的小数量理论
- 氧微积分
- 教堂–罗瑟定理
Y组合的实现匿名递归。因此,不是的
function fib( n ){ if( n<=1 ) return n; else return fib(n-1)+fib(n-2) }
你可以做的
function ( fib, n ){ if( n<=1 ) return n; else return fib(n-1)+fib(n-2) }
当然,y-只有组合的工作在按名的语言。如果你想使用此在任何正常的电话通值的语言,然后你会需要的相关z组合(y组合将出现分歧/无限循环)。
作为一个新手来组合子,我发现 迈克*凡尼尔的文章 (感谢尼古拉斯Mancuso)是真的很有帮助。我想写一个概要,除了记录我的理解是,如果这可能有助于其他一些人,我将非常高兴。
从 蹩脚 要 少蹩脚
使用因子为例,我们用以下的 almost-factorial
功能的计算因子的数量 x
:
def almost-factorial f x = if iszero x
then 1
else * x (f (- x 1))
在上述伪码, almost-factorial
需要在功能 f
和数量 x
(almost-factorial
是咖喱,所以它可以看作在功能 f
和返回的一个1-数功能)。
时 almost-factorial
计算因子为 x
, 它代表计算的因为 x - 1
功能 f
和积累,结果与 x
(在这种情况下,它繁殖的结果(x-1)x)。
它可以被看作是 almost-factorial
需要在一个 蹩脚 版本因素的功能(这只能计算,直到号码 x - 1
)和返回 不太蹩脚 版本的因子(其中计算,直到号码 x
).作为在这种形式:
almost-factorial crappy-f = less-crappy-f
如果我们反复通过 不太蹩脚 版本的因素, almost-factorial
, 我们最终将获得我们所希望的因素的功能 f
.在那里它可以被认为是为:
almost-factorial f = f
修正点
事实上, almost-factorial f = f
装置 f
是的 修正点 的功能 almost-factorial
.
这是一个非常有趣的方式看的关系的职能上,这是一个哈时刻对我来说。(请阅读迈克的后在解决-一点如果你还没有)
三个功能
一概而论,我们有一个 非recursive 功能 fn
(像我们几乎因素),我们有它 修正点 功能 fr
(喜欢我们的f),然后是什么 Y
不是当你得到 Y
fn
, Y
返回的修正点的功能 fn
.
因此,在总结(简化的假设 fr
只需要一个参数; x
堕落到 x - 1
, x - 2
...在递归):
- 我们定义的 核心计算 作为
fn
:def fn fr x = ...accumulate x with result from (fr (- x 1))
, 这是的 几乎的-有用的 功能--尽管我们不能使用fn
直接上x
, 它将是有用的很快。这不递fn
用一个功能fr
计算结果 fn fr = fr
,fr
是的修正点的fn
,fr
是的 有用的 主要功能,我们可以使用fr
上x
让我们结果Y fn = fr
,Y
返回的修正点的功能,Y
变成我们 几乎的-有用的 功能fn
入 有用的fr
得出 Y
(不包括)
我会跳过导的 Y
去了解 Y
.迈克Vainer后有很多的细节。
形式 Y
Y
被定义为(在 氧微积分 格式):
Y f = λs.(f (s s)) λs.(f (s s))
如果我们替代变量 s
在左边的功能,我们得到
Y f = λs.(f (s s)) λs.(f (s s))
=> f (λs.(f (s s)) λs.(f (s s)))
=> f (Y f)
所以事实上的结果 (Y f)
是的修正点的 f
.
为什么 (Y f)
工作?
根据签名的 f
, (Y f)
可以是一个函数的任何数,以简化,让我们假设 (Y f)
只需要一个参数,就像我们的因素的功能。
def fn fr x = accumulate x (fr (- x 1))
由于 fn fr = fr
, 我们继续
=> accumulate x (fn fr (- x 1))
=> accumulate x (accumulate (- x 1) (fr (- x 2)))
=> accumulate x (accumulate (- x 1) (accumulate (- x 2) ... (fn fr 1)))
递归算终止时,最里面 (fn fr 1)
是的基本情况和 fn
不使用 fr
在计算。
看 Y
再次:
fr = Y fn = λs.(fn (s s)) λs.(fn (s s))
=> fn (λs.(fn (s s)) λs.(fn (s s)))
所以
fr x = Y fn x = fn (λs.(fn (s s)) λs.(fn (s s))) x
我说,神奇的部分安装是:
fn
和fr
interdepend上每一个其它:fr
'包装'fn
在内部,每个时间fr
用于计算x
, 这会产生'('电梯'?) 一个fn
和代表的计算,fn
(通过在本身fr
和x
);另一方面,fn
取决于fr
和使用fr
计算结果较小的问题x-1
.- 在时间
fr
用来定义fn
(当fn
使用fr
在其运作),该实fr
尚未定义。 - 它的
fn
它定义了真正的商业逻辑。基于上fn
,Y
创建fr
-一个辅助功能在一个具体的形式,以便于计算fn
在一个 递归 方式。
它帮助我了解 Y
这样的时刻,希望这有所帮助。
顺便说一句,我还找到了这本书 介绍编程功能,通过氧微积分 很好,我只是部分通过它与事实上,我不能让我的头周围 Y
在书中,导致我到这一员额。
这里有答案 原来的问题, 汇编从 该文章 (这是完全值得一读)中提到的 答案由尼古拉斯Mancuso, 以及其他的答案:
什么是Y-组合?
一个Y组合是一种"功能性"(或者更高的阶函数的一个函数的运作上的其他职能),需要一个单一的论点,这是一个函数,并不递归,并返回一个版本的功能是递归的。
有些递归=),但更深入的定义:
一个组合—只是一个lambda的表达有没有免费的变量。
免费的变是一个变量,不一定变量。
定变量的变量载体内部的一氧表达了变量名称作为其论据。
另一种方式来想想这个是组合就是这样一个lambda表达,你是能够替换该名称一个组合与其定义无处不在,它是找到和拥有的一切仍然可以工作(你会进入一个无限的循环,如果组合将包含参考本身内部的氧体)。
Y组合是一个固定点的组合.
固定点的一个函数是一个元素的功能领域就是映射到本身的功能。
这就是说, c
是一个固定点的功能 f(x)
如果 f(c) = c
这意味着 f(f(...f(c)...)) = fn(c) = c
如何组合子的工作?
下面的例子承担 强大的动态 键入:
懒惰的(正常秩序)Y组合的:
这个定义适用于语言与懒(:推迟了,电话分需要)评价评估的战略,延缓评估的一种表达,直到它的价值是必要的。
Y = λf.(λx.f(x x)) (λx.f(x x)) = λf.(λx.(x x)) (λx.f(x x))
这意味着,对于一个特定功能 f
(这是一个非递归功能),相应的递归功能,可以获得第一个通过计算 λx.f(x x)
, ,然后应用该lambda表达本身。
严格的(应用阶)Y组合的:
这个定义适用于语言的严格(也:渴望,贪婪的)评价,评价战略,在其中一个表达式进行评估时,尽快开一个变量。
Y = λf.(λx.f(λy.((x x) y))) (λx.f(λy.((x x) y))) = λf.(λx.(x x)) (λx.f(λy.((x x) y)))
它是一样的懒之一,在它的性质,它只是有一个额外的 λ
包装推迟lambda的体评价。我们已经问了 另一个问题, 有点有关这个问题。
它们是什么好处?
偷来的 借用 答案由克里斯*Ammerman:Y组合的概括递归,抽象其实施,并由此脱离实际工作的职能中的问题。
即使Y组合中有一些实际应用,它主要是一个理论概念,了解其将扩大你的整体愿景,并将有可能提高你的分析和开发技能。
他们是有用的,在程序性的语言?
作为 说迈克*凡尼尔: 它是可能的定义Y组合,在许多类型的静态语言,但是(至少在例子我已经看到的)这样的定义通常需要一些非显而易见的类型车呀,因为Y组合本身没有一个简单的静态型的。这超出了本文的范围,所以我不会提到这一步
和为 提到克里斯Ammerman:大多数程序性的语言有静-打字。
所以回答这一个—不是真的。
一点固定组合(或定点操作员)是一个高阶函数计算的固定点的其他职能。这种操作是相关的,在编程语言论,因为它允许执行递归的形式重写规则,而不明确的支持,从语言的运行发动机。(src维基百科)
这个运营商可以简化你的生活:
var Y = function(f) {
return (function(g) {
return g(g);
})(function(h) {
return function() {
return f.apply(h(h), arguments);
};
});
};
那么你避免额外的功能:
var fac = Y(function(n) {
return n == 0 ? 1 : n * this(n - 1);
});
最后,你呼叫 fac(5)
.
我认为最佳的方式回答这个是选择一种语言,例如JavaScript:
function factorial(num)
{
// If the number is less than 0, reject it.
if (num < 0) {
return -1;
}
// If the number is 0, its factorial is 1.
else if (num == 0) {
return 1;
}
// Otherwise, call this recursive procedure again.
else {
return (num * factorial(num - 1));
}
}
现在重写,使其不使用名称的功能内部的功能,但是仍然呼它。
只有名称的功能 factorial
应该看到是在电话网站。
提示:你不能使用名称的功能,但是可以使用的名称参数。
工作的问题。不看看它。一旦你了解决它,你就会明白什么问题y组合的解决。