咖喱函数(Curry Func)

来源:互联网 发布:淘宝网肚皮舞服装 编辑:程序博客网 时间:2024/04/27 16:25

文 / 李博(光宇广贞)

Wikipedia, the Imperialistic encyclopedia

       In mathematics and computer science, curring, invented by Moses Schönfinkel and later re-invented by Haskell Curry, is the technique of transforming a function that takes multiple arguments (or more accurately an n-tuple as argument) in such a way that it can be called as a chain of functions each with a single argument.


       Haskell B. Curry(1900-1982),美国数学家。著名的 Haskell 纯函数式语言(1990-)其命名取自他的名字即为纪念。他生前贡献良多。与本文相关的,他是计算数学中的“函数咖喱(Curring)”思想的完善者。
       函数咖喱说白了即为参数的分步代入。当函数所有参数无法同时提供时,有两种方案:1、保存已提供参数,等待其它参数准备好再一齐传入函数;2、使用已有参数与函数生成新函数,接收所剩其它参数。第二种即为函数咖喱,生成的函数组成咖喱函数链。相关的示例随处可见,比如维基百科上的示例。
       函数咖喱在密集型计算中可方便地让传入闭包(Closure)内的函数组构建成一条流水线而不用考虑线程同步问题,此也即 CPS 思想。这是函数式(FP)语言相比命令式(IP)语言的巨大优势,也是 Lambda-Calculus 真正体现其威力之处。
       支持闭包的语言均可使用闭包去操作函数咖喱,或者换句话说,能否使用某种语言所实现的闭包去操作函数咖喱成为该语言是否完善支持闭包概念的判断依据。很多语言使用 Lambda 表达式作为表达闭包概念的工具。
Haskell_Logo

       咖喱函数的数学表示如下:

       设函数 F 有 n 个参数,每个参数的定义域分别为 D1 到 Dn,函数 F 值域为 Dr:
       F: D1 * D2 * … * Dn –> Dr

       等价咖喱表达式为:
       curry( F ): D1 –> ( D2 –> … –> ( Dn –> Dr ) )

       如上表达式是一个“简单类型 Lambda 演算”式,它呈现了开篇引述的诠释,每次接收一个参数而构成的函数传递链。每个括号内的操作完成后,都产生新的只需接收所剩参数的函数。新函数的值域不变。如是沿链次第操作,直至函数 F 计算完成,返回最终结果。

       C、C++、Obj-C 语言模拟咖喱函数参见《Dami91a.pdf》。


       IP 语言对咖喱函数只能说是“模拟”,谈不上完全实现。两个缺陷制约 IP 的表现:1、函数类型推导和检查;2、编译器优化

       第一点,C 的函数类型太弱,可以退化为只有机器字长的指针而无法约束。动态语言如 Python 等则谈不上有函数类型检查;而静态 OOP 语言如 C# 等函数被束缚在对像内,类型检查则被高架在对像层面,使得 OOP 语言仅可通过类算符重载来有限模拟以达到类型检查的效果。C++ 显得更尴尬,无论用类 C 的手段还是 OOP 手段都达不到要求。 
       第二点,篇末参考中第一篇《函》指出 C++ 和 C# 的 CPS 实现尾递归计算草草地便堆栈溢出而失败,表现远不如函数式语言 F#。编译器无法根据编译期提供的信息去优化代码,这一缺陷在递归运算中体现出来。

       这两点使 IP 语言模拟咖喱函数不能保证安全、便捷、高效。随后 IP 语言家族中各成员纷纷引入 Lambda 表达式来弥补这一先天的缺陷,然而效果差强人意。比如无论 C++0x 还是 C# 对 Lambda 的类型推导都没能给程序员以足够的解放,且对 Lambda 表达式的优化都没有实现。


       本文只是言简意赅地介绍一下“咖喱函数”。咖喱函数的基础在于 Lambda-Calculus,即 Λ-演算。请见《Lambda 演算和函数式语言》。


       所属分类:F#.netC++C#.net数学和算法计算机技术杂文

       参考:

       函数式编程魅力:Continuation-Passing Style,说为何 C#、C++ 引入 Lambda 意义重大及 C++ 和 C# 的缺憾

       C++ 0x 之 Lambda:贤妻与娇娃,你娶谁当老婆?听 FP 如何点化 C++

       方法多态与Duck typing;C#之拙劣与F#之优雅