博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用F#编写、理解Y组合子函数
阅读量:5290 次
发布时间:2019-06-14

本文共 1337 字,大约阅读时间需要 4 分钟。

 赵劼的博客《》中用C#实现了为函数求出 Y 组合子的函数。C#代码生涩,难以阅读,原代码如下:

static Func
Fix
(Func
, Func
> f) { return x => f(Fix(f))(x); } static Func
Fix
(Func
, Func
> f) { return (x, y) => f(Fix(f))(x, y); }

 代码调用如下

var fac = Fix
(f => x => x <= 1 ? 1 :x * f(x - 1));

 让代码变得容易阅读原是F#的强项,我们尝试用F#重写上面的代码,把 Fix 函数改名为 Y,得出以下代码: 

let rec Y f x = f (Y f) x

 代码调用则如下

let fac =        Y (fun yf x ->                if x <= 1 then 1                else x * yf(x - 1))

现在,Y 组合子函数一下子就明撩了:它就是定义了一个高阶函数 Y,其部分实现为:  Y f = f (Y f) 

我们检视 fac 函数中的 Y f ,这里,参数 f 其实就是匿名函数 fun yf x -> ...

 关键: 这里参数 yf 被代入值 Y f,而 Y f 等于 fac,因此上,实质上变成: 

let fac =    fun x ->        if x <= 1 then 1        else x * fac(x - 1)

 

OK,现在如果在 let 后面加上  rec  ,那就成为一个标准的递归函数了。

 

另外,需要注意的是: let rec Y f x = f (Y f) x 不能改写为 let rec Y f = f (Y f)

理论上,两者的 Y 等义,但是,后者会在 被调用时,先计算出 Y f 的值,最后因为无法结束递归而导致堆栈溢出。 

而前者不计算 Y f,直接计算 Y f x,在 x <= 1 时候停止递归

================================================================================

什么?Y 组合子有什么用?就是在你需要使用匿名函数,但是同时需要递归的时候,有了 Y 组合子你才可以同时拥有两者。

譬如,可以这样: 

a        |> (+) 4        |> Y (fun yf x ->                    if x <= 1 then 1                    else x * yf(x - 1))

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/greatim/p/4474454.html

你可能感兴趣的文章
第十章、logging模块
查看>>
第十章、typing模块
查看>>
第十章、numpy模块
查看>>
第十章、jupyter入门之pandas
查看>>
第十章、collections
查看>>
第十一章、面向对象及类与对象
查看>>
第十一章、定制对象独有特征
查看>>
第十一章、类和数据类型
查看>>
第十一章、类的继承
查看>>
第十一章、对象属性查找顺序与属性和方法
查看>>
0827作业
查看>>
第十一章、菱形继承问题
查看>>
第十一章、super()详解
查看>>
第十一章、面向对象之多态、多态性
查看>>
第十一章 面向对象之类的组合
查看>>
第十一章、类的封装
查看>>
第十三章、元类(metaclass)
查看>>
第十三章、元类之控制类的产生
查看>>
第十三章、元类之控制类的调用过程
查看>>
原创博客>>>解决粘包问题的方法
查看>>