网易首页 > 网易号 > 正文 申请入驻

探索匿名递归函数

0
分享至

  匿名递归

  在 C# 里递归可以这么定义吗?

  Func fac = (x) => (x <= 1) ? 1 : x * fac(x - 1);

  目前不行。因为 C# 只认识下面这种写法:

  Func int> fac = null ;
fac = (x) => (x <= 1 ) ? 1 : x * fac(x - 1 );

  但这实际上并未使该函数匿名化,而是把变量fac的引用绑定到了匿名函数的上下文中。这在变量fac被修改后存在失效的风险。

  将自己传给自己

  为了使匿名递归可行,必须将自身作为参数传给自己。

  这么写可行吗?

  var fac = (f, x) => (x <= 1 ) ? 1 : f(f, x - 1 );
fac(fac, 5 );

  在 C# 里不行。因为 fac 的类型签名无法被自动推断,需要人工提供。

  delegate int SelfFactorial(SelfFactorial f, int x);

  写成泛型,提高通用性:

  delegate TResult SelfApplicable TResult>(SelfApplicable TResult> self, T arg);
SelfApplicable int> fac = (f, x) => (x <= 1 ) ? 1 : f(f, x - 1 );
fac(fac, 5 );

  更进一步,为 fac 构建函数闭包,得到我们想要的函数形式:

  Func Fac = (x) => fac(fac, x);

  综合以上过程,给出一个通用形式的帮助函数,简化类型推断:

  static Func Make(SelfApplicable self)
{
return (x) => self(self, x);
}

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

  推广到两个参数的情形:

  delegate TR SelfApplicable(SelfApplicable self, T1 arg1, T2 arg2);

  static Func Make(SelfApplicable self)
{
return (x, y) => self( self, x, y);
}

  var gcd = Make< int, int, int>((f, x, y) => (y == 0) ? x : f(f, y, x % y));

  但类型推断并不是什么大问题,下文如因类型推断而无法写出,大可手动补上。

  柯里化

  柯里化即将多参数的函数转化为多个单参数函数的嵌套。

  你可能会想到这种写法:

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

  这需要配套怎样的Make2呢?

  static Func Make2(Func, Func> g)
{
// 建立一个新的上下文,在里面用上 g 就能把 g 保存起来。
var wrapped_k = (x) => {
// 先跳过这行分析下面的,因为 h 是为了传给 g 做参数的。
// 这个操作必须在子函数体内,不然就死循环了。
var h = Make2(g);
// k 才是想要的那个功能函数,但获得这个 k 之前没法传给 g 做其参数 f,陷入了鸡生蛋蛋生鸡的矛盾。
// g 的参数 f 无法是 k,但 Make2 能构造 k 的转发函数,且转发函数使用时才会计算,不会死循环。
var k = g(h);
k(x);
};
// 这是一个 k 的转发函数,用起来就跟 k 没什么区别。而且它的上下文里有 g 的引用。
return wrapped_k;
}

  这是一个不动点组合子(将在下文中解释其含义),让我们先将其重命名为Fix

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

  Fix要配合一种两层的匿名函数写法。其中递归函数自身作为外层函数的参数,Fix将其转化为了可以直接使用的函数对象。

  两个参数的Fix函数也可以顺利写出来了:

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

  // g0 也可称为单步函数
var g0 = (f) => (x) => (x <= 1) ? 1 : x * f(x - 1);
var fac = Fix(g0);
fac( 5);

  var g1 = (f) => (x, y) => (y == 0) ? x : f(y, x % y);
var gcd = Fix(g1);
gcd( 10, 15);

  先把单步函数抽象一下:

  // use(x) 产生当次执行的计算结果
// next(f, x) 递归地产生 f(x),或是在没有下一个 x 时及时终止
// reduce(a, b) 将当次与递归的结果合并为最终结果
var g = (f) => (x) => reduce(use(x), next(f, x));

  以一个参数的Fix函数为例分析其过程。

  先分析这个两层匿名函数g,并将内层函数单独称为 k:

  // 注意:这是方便理解而拆开的伪代码,因为不可能使 k 在没有 f 的上下文中绑定到 f。类型推断也是个问题。
var k = (x) => reduce(use(x), next(f, x));
var g = (f) => k;

  var f0 = Fix(g) = (x) => g(Fix(g))(x);

  这里的参数x被直接转发给了内部函数h(Fix(g)),因此我们可以在分析时简化。

  var f0 = (x) => k(x), f=Fix(g);

  虽然每次f=Fix(g)计算得到一个新的函数对象而不是复用已得到的f0,但二者的效果是相同的。

  这里有一个等式:

  g(Fix(g)) == Fix(g)

  一般地,我们称值x是函数f的一个不动点,当且仅当f(x) = x

  那么根据上文中的两个等式,值Fix(g)是函数g的一个不动点。

  Y-组合子

  Y-组合子定义为:

  Y = λf.(λx.f (x x)) (λx.f (x x))

  注意:根据 α-变换,两个 λx 是不同的变元,互不影响。即上式与下式等价:

  Y = λf.(λx.f (x x)) (λy.f (y y))

  但只要表达式相同,自由变元的名字无关紧要,所以在两个不同的地方都用λx是没问题的。

  拆分一下,方便理解:

  h = λx.f (x x)
Y = λf.h h

  写成 C# 是:

  var Y = (f) => {
// 这虽然写得出代码,但执行起来会死循环
var H = (x) => f(x(x));
return H(H);
};

  因此这里需要多一层转发函数的嵌套,使x(x)被推迟执行。推迟执行最重要的目的是在递归到头的时候不再计算从而能够退出。

  增加一层转发函数,这对应于 λ-演算,即可以使用 η-变换。有两个做法:

  x x展开为λv.(x x) v

  f (x x)展开为λv.(f (x x)) v

  第二种变换对应的 C# 是:

  var Y = (g) => {
var H = (h) => {
var wrapped_k = (x) => {
// 每次 h(h) 都得到一个新的 wrapped_k
var new_wrapped_k = h(h);
// 在 wrapped_k 中使用了 g
// 换取真正的功能函数,而 new_wrapped_k(next(x)) 是能递归下去的
var k = g(new_wrapped_k);
return k(x);
};
return wrapped_k;
};
// 巧妙的 H(H), h(h) 组合,创建对 g 的闭包
return H(H);
};

  简写为:

  var Y = (g) => {
var H = (h) => (x) => g(h(h))(x);
return H(H);
};

  Θ-组合子

  var H = (h) => (g) => (x) => g(h(h)(g))(x);
var Θ = H(H);

  Θ-组合子 与 Y-组合子 的唯一区别就是变量 g 在多层函数的位置,以及因此而需要的一个重复传参的步骤。

  这两个组合子的对比同时说明了以下等式:

  λx.λy.((f x y) y0 x0) == λy.λx.((f x y) x0 y0)

  END

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
庚欣:赖清德“台独自白”,美国怎么想?

庚欣:赖清德“台独自白”,美国怎么想?

直新闻
2024-05-22 22:42:43
3-0利物浦、3-0马赛、3-0勒沃库森!亚特兰大几乎通杀前6联赛

3-0利物浦、3-0马赛、3-0勒沃库森!亚特兰大几乎通杀前6联赛

直播吧
2024-05-23 13:04:13
解气!日本女星森星抢刘亦菲、舒淇位置,直接被活动主办方除名

解气!日本女星森星抢刘亦菲、舒淇位置,直接被活动主办方除名

萌神木木
2024-05-21 19:37:50
苹果宣布史上最大降价:最高降价2300元

苹果宣布史上最大降价:最高降价2300元

三言科技
2024-05-21 08:02:05
网传昆山某企业放假,公司全额承担社保和公积金!发放工资2490元

网传昆山某企业放假,公司全额承担社保和公积金!发放工资2490元

火山诗话
2024-05-22 14:08:32
记者:孔帕尼现在不在慕尼黑,拜仁决定不支付2000万欧费用

记者:孔帕尼现在不在慕尼黑,拜仁决定不支付2000万欧费用

直播吧
2024-05-23 19:05:10
广东女子晒“豪横”一人餐走红,仪式感十足,网友:家里有矿吧?

广东女子晒“豪横”一人餐走红,仪式感十足,网友:家里有矿吧?

沫姐美食记
2024-05-22 08:30:19
专家竟沦为境外间谍 !泄露大量核心技术机密

专家竟沦为境外间谍 !泄露大量核心技术机密

每日经济新闻
2024-05-23 10:38:57
刘国梁曾经采访时谈到马琳:“不少球员都表示和马琳打一场球下来在厕所都会嗷嗷吐

刘国梁曾经采访时谈到马琳:“不少球员都表示和马琳打一场球下来在厕所都会嗷嗷吐

阿牛体育说
2024-04-30 07:30:08
祸从口出1:聂慧广州做买卖,聂磊出资

祸从口出1:聂慧广州做买卖,聂磊出资

金昔说故事
2024-05-23 19:15:45
女性绝经后,或出现3个难言之隐,医生直言:很正常,别不好意思

女性绝经后,或出现3个难言之隐,医生直言:很正常,别不好意思

资说
2024-05-23 17:01:03
新华简讯|以色列战时内阁决定继续与哈马斯谈判

新华简讯|以色列战时内阁决定继续与哈马斯谈判

新华社
2024-05-23 20:52:10
自信过头了!去年拒绝1.5亿,今年被扫地出门,不会投篮还这么狂

自信过头了!去年拒绝1.5亿,今年被扫地出门,不会投篮还这么狂

球毛鬼胎
2024-05-22 12:50:28
再见了,二维码!央行正式宣布,支付宝、微信迎来强大的"对手"

再见了,二维码!央行正式宣布,支付宝、微信迎来强大的"对手"

白茶之清欢
2024-05-23 21:25:05
美国智库警告:台海之战的规模,会庞大到让美国都“无法理解”!

美国智库警告:台海之战的规模,会庞大到让美国都“无法理解”!

小阿文热点军
2024-05-23 20:45:44
3艘印度军舰抵菲,莫迪有两个目的,中方不反制,新德里不会清醒

3艘印度军舰抵菲,莫迪有两个目的,中方不反制,新德里不会清醒

娱乐白兔
2024-05-23 19:45:19
黄春梅爆料:女儿已经被具俊晔彻底拿捏!他手里掌握大S大量把柄

黄春梅爆料:女儿已经被具俊晔彻底拿捏!他手里掌握大S大量把柄

袁小二先生
2024-05-23 00:45:02
明星绯闻大揭秘:王一博肖战国外领结婚证?张艺兴非法拿编制?娜扎抱团排挤迪丽热巴?徐海乔宣璐恋情曝光?欧弟未婚生三胎?

明星绯闻大揭秘:王一博肖战国外领结婚证?张艺兴非法拿编制?娜扎抱团排挤迪丽热巴?徐海乔宣璐恋情曝光?欧弟未婚生三胎?

娱乐的小灶
2024-05-22 22:41:02
中国历史的“黄巢时刻”,细思恐极

中国历史的“黄巢时刻”,细思恐极

最爱历史
2024-05-22 16:22:34
蔡国庆官宣喜讯:为国争光,大儿子在国际大赛上获“世界赛冠军”

蔡国庆官宣喜讯:为国争光,大儿子在国际大赛上获“世界赛冠军”

兰子记
2024-05-22 23:52:52
2024-05-23 22:10:44
开源中国
开源中国
每天为开发者推送最新技术资讯
6289文章数 34218关注度
往期回顾 全部

科技要闻

黄仁勋业绩会万字实录:我们的压力太大了

头条要闻

媒体:大陆对赖清德彻底失望 或先收回几个离岛控制权

头条要闻

媒体:大陆对赖清德彻底失望 或先收回几个离岛控制权

体育要闻

欧文,三十二而立

娱乐要闻

大S儿子被学校退学,张兰称孙子没人管

财经要闻

九鼎金租减值罗生门:郑州银行藏雷?

汽车要闻

上汽大通大家7超混/大家9超混将于6月7日正式上市

态度原创

艺术
家居
教育
时尚
手机

艺术要闻

穿越时空的艺术:《马可·波罗》AI沉浸影片探索人类文明

家居要闻

光阴流年 摇曳爱恋

教育要闻

交警进校快问快答,小学生机智避“坑”

去了杭州才发现:满大街都在穿“超短裙+长筒袜”,时髦又显瘦

手机要闻

2699元起,Reno12系列要做今年最靓的小直屏?

无障碍浏览 进入关怀版