• Y Combinator


    常见的例子

    阶乘函数:

    fact = (a) -> if a > 0 then a * fact(a - 1) else 1

    问题的提出

    如上,在fact函数中调用了fact本身,无法使用匿名函数表达,如何解决这一问题?

    初步的尝试

    初始的f:

    f = (a) -> if a > 0 then a * f(a - 1) else 1

    第一步,去除自身的递归调用:

    f1 = (a) -> if a > 0 then a * f(a - 1) else 1

    第二步,f1调用了f,将f提出,使得f'只依赖于输入:

    f' = (f) -> (a) -> if a > 0 then a * f(a - 1) else 1

    第三步,将f代入:

    f' f = f

    数学中,f(x)=x,此时x为f(x)的不动点;

    同样的,f'(f)=f,此时f为f'的不动点。

    此时,f(x)=f'(f(x)),接下来就是求f'。

    进一步探索

    当前的问题:求f'

    令f=Y f',求解f与f'之间的关系。

    这时有:

    f = Y f'

    进而有:

    f = f' f = Y f' = f' Y f'

    得出:

    Y = f -> f Y f

    故而我们需要求出Y组合子(Y Combinator)。

    Y组合子

    现成的Y组合子:

    Y = f -> (x -> f x x) (x -> f x x)

    证明:

    Y g = (x -> g x x) (x -> g x x)

          = (x -> g x x) (x -> g x x)

          = g (x -> g x x) (x -> g x x)

          = g Y g

    其他组合子:

    Z = f -> (x -> f (y -> x x y)) (x -> f (y -> x x y))

    Y' = (x -> y -> x y x) (y -> x -> y x y x)

    Θ = (x -> y -> y x x y) (x -> y -> y x x y)

    问题的解决

    对阶乘函数fact:

    fact = (f) -> (a) -> if a > 0 then a * f(a - 1) else 1

    有:

    Y fact = fact Y fact

              = (a) -> if a > 0 then a * (Y fact)(a - 1) else 1

    这样,Y fact实现了和阶乘函数一样的功能。

    可以写出:

    fact = ((f) -> ((x) -> (n) -> (f x x)(n)) ((x) -> (n) -> (f x x)(n))) (f) -> (a) -> if a > 0 then a * f(a - 1) else 1

    JS调用fact(5):

    (function(f) {
        return (function(h) {
            return h(h)
        })(function(x) {
            return function(n) {
                return f(x(x))(n)
            }
        })
    })(function(f) {
        return function(n) {
            return n > 0 ? n * f(n - 1) : 1
        }
    })(5)

    总结

    综上可知,匿名函数可写成Y(f),f的类型为f->TInput->TResult,则Y的类型为(f->TInput->TResult)->TInput->TResult

  • 相关阅读:
    asp.net core 参数使用
    dotnetcore EF 表达式
    dotnetcore EF 查询筛选
    flowable流程中心设计之子流程(九)
    Spring Boot源码阅读如何加载环境变量(二)
    flowable流程中心设计之网关(八)
    idea阅读源码无download source解决方式
    Spring Boot源码阅读如何启动内置web容器(三)
    InheritableThreadLocal源码阅读
    Spring Boot源码阅读启动主流程(一)
  • 原文地址:https://www.cnblogs.com/bajdcc/p/5757410.html
Copyright © 2020-2023  润新知