函数式编程中的对偶性方法

时间:2011-04-05 20:05:21

标签: math haskell functional-programming

我想知道函数式编程中“对偶方法”可以解决什么样的现实问题。更准确地说,我想知道是否有人确实使用了我下面提到的二元方法,或者是否有其他有趣的例子。我对现有的实现特别感兴趣,可能在Haskell中。

[由于大多数对这个问题感兴趣的人可能都知道Haskell,请允许我添加Haskell标签,即使这个问题与语言无关]

让我通过几个例子来解释我所说的二元性(缺乏一个更好的名字)。第一个是实数。假设存在IntegerRational类型,并将实数定义为函数(原谅我的Haskell,我不是铁杆的哈克勒)

type Real = Integer -> Rational

这样,只要x :: Real表示实数x,x n就会产生一个在x的2^(-n)范围内的有理数。

现在可以做到

(+) :: Real -> Real -> Real
(+) x y n = (x $ n + 1) + (y $ n + 1)

或类似地用于其他算术运算。给定连续的实函数f,只要可以为f x计算modulus of continuity,就可以计算f

这样做的好处是可以编写自然的代码,最后自动获得所需的精度。但是,不再可能比较实数是否相等。 xy之间唯一可能的比较是x < y + eps

二元性的另一个例子是this question on probability measures,它引发了我脑海中的当前问题。让我们写一下

type Measure a = (a -> Double) -> Double

并将度量定义为针对函数的集成过程。在链接的问题中,我展示了在这个框架中表达诸如卷积或前推之类的概念是多么自然,这些概念在概率密度的水平上定义要困难得多(在计算上,但在理论上也是如此)。 / p>

它允许人们从概率论中构建构建块,原则上允许人们构建复杂的蒙特卡罗程序,甚至允许人们使用显式概率密度(以数值积分为代价)。我对这个主题的真实世界图书馆的任何尝试都特别感兴趣。

我想到的另一个例子,但还没有完全形式化的是矢量场(来自微分几何)的概念,可以表示为微分算子 。为此,需要一种合适类型的“平滑实值函数”,然后矢量场就像这样:

type VectorField = SmoothFunction -> SmoothFunction

这样v (f * g) = f * (v g) + g * (v f)

当然,在Haskell中描述一堆常规函数应该不容易。但通过这样做,我们可以以完全独立的方式表达所有来自微分几何的东西,并在最后插入坐标。

还有其他例子,例如。 泰勒系列已在Sigfpe的博客中讨论过(虽然我找不到这篇特别的帖子),其中分析函数的类型如下:

type AnalyticFunction = Double -> Integer -> [Double]

并且f x n返回n围绕f x的泰勒展开的f / g首部分和。这允许我们在分析函数上无缝地编写所有类型的算法,包括像f这样的东西,其中gf^(-1)都可以在某一点上消失(以及它们的一些衍生物),或者偶f'(提供{{1}}不会消失)。最后,只计算中间序列的必要项以产生给定表达式的值。

1 个答案:

答案 0 :(得分:32)

您的示例的共同特征是通过函数表示某些(数学)对象。这在函数式语言中很常见,但不像数学那样实用,因为程序中的函数是扩展使用的(你不能检查它们的定义,只能观察它们对参数的作用),并且只能用可计算的操作(你只能观察有限数量的参数)。

在数学中,你不必费心这些东西,例如你经常说“如果f是解析,那么让(a_n)成为它的系数序列,并且......”。在计算机语言中,如果从类型Double -> Integer -> [Double]的函数开始,将它转换为可以轻松恢复系数的表示将会很痛苦。在编程语言中,函数真的是黑盒子。

出于这个原因,程序员经常尝试使用显式数据表示而不是功能黑盒子。您可以轻松地从数据表示中获取函数(它是一种评估或解释),而另一种方式可能更难,效率更低等。请参阅Conal Elliott的“Everything is a function” in Haskell?

然而,在我们真正需要拉伸对象的情况下仍然使用函数,这些对象只能被观察而不是被检查。对于要定义的对象的每个可能的观察,您将提供实现此观察的功能。在您的示例中,您只有一个函数,因为您只有一个观察。这是William Cook在他的On Understanding Data Abstraction, Revisited论文中定义的面向对象编程的核心思想。

我认为你将这与“二元性”这个术语联系起来的原因(在Haskell知识分子中,与类别理论概念相关的术语)是指从一个物体转向一种特定的观察形式。它有时被称为数学中的二元性,并且具有在任何地方添加函数的效果。例如,有一个向量空间对偶的经典例子,特别是双向构造,它实际上是从向量到线性函数观察的转换:你从V切换到{{1} },用于(V -> K) -> K矢量空间下面的字段。

(会不会想到延续阅读我的最后一个例子?当然这些是相关的,因为这种延续的表示实际上是对具体评价背景的“观察”,以他们对价值的行为来表示。)

您对概率度量的表示实际上用于定义函数式语言中的概率度量单子。有不同的方法来定义概率单子。参见Norman Ramsey和Avi Pfeffer的例如http://www.cs.tufts.edu/~nr/pubs/pmonad-abstract.html。然而,概率DSL的大多数实际实现使用更具体的表示,例如K对列表(Haskell probability库和OCaml HANSEI)。

最后,有关将实数表示为函数的示例,请参阅Russel O'Connor的A Monadic, Functional Implementation of Real Numbers。存在许多“可计算”数字的表示并且具有不同的优点,并且它们中的大多数基于序列,因此可以表示为[(prob,event)]函数。