Haskell中flip函数的定义

时间:2019-06-10 15:29:03

标签: haskell functional-programming higher-order-functions

目前,我正在尝试通过“学习您的Haskell”一书来学习Haskell,并且试图了解chapter 5flip函数的实现。问题在于作者声明如果g x y = f y x有效,则f y x = g x y也必须为真。但是这种反转如何以及为什么会影响两个函数定义?

我知道currying的工作方式,并且我也知道->运算符在默认情况下是右关联的,因此类型声明实际上是相同的。我也了解彼此分开的功能,但不了解g x y = f y x的反转与此相关。

第一个翻转功能

flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f = g
    where g x y = f y x

第二次翻转功能

flip' :: (a -> b -> c) -> b -> a -> c
flip' f y x = f x y

2 个答案:

答案 0 :(得分:7)

我认为作者脑海中的论点被粗略地缩写为一点都不合理。但是这是我对推理的猜测。我们从第一个定义开始:

flip f = g where g x y = f y x

现在,我们观察到这是一件令人毛骨悚然的事情,并且我们使用(->)和垃圾的所有关联性讨论来写相同的东西,但是对f有两个额外的论点。像这样:

flip f x y = g x y where g x y = f y x

现在我们得到了他双向调用的方程:g x y = f y x,反之亦然。我们可以使用以下公式重写flip的主体,如下所示:

flip f x y = f y x where g x y = f y x

由于定义的正文不再提及g,因此我们可以将其删除。

flip f x y = f y x

现在我们几乎在那里。在最终定义中,作者在各处交换了名称xy。我不知道他们为什么选择这么做,但这是您可以在方程式推理中做出的合法举动,所以在那里没有问题。这样做为我们提供了最终方程:

flip f y x = f x y

答案 1 :(得分:3)

flip接受一个函数并返回该函数的翻转版本。定义flip'的一种方法是将应用程序包含在定义本身中,因为

flip' f y x = f x y  ===> flip' f y = \x -> f x y
                     ===> flip' f = \y -> \x -> f x y

也就是说,flip' f是一个将f以相反顺序应用于其自变量的函数。

第二个定义只是简单地给匿名函数\y -> \x -> f x y命名,然后使用该名称作为flip' f x y的定义。

                     ===> flip' f = g where g = \y -> \x -> f x y
                     ===> flip' f = g where g y = \x -> f x y
                     ===> flip' f = g where g y x = f x y

也就是说,flip' f是某个函数g,其中g被定义为以相反的顺序将f应用于g的自变量。

定义g x y = f y xg y x = f x y等效于alpha conversion。在这两种情况下,f都是g定义中的自由变量; g作为对f的{​​{1}}参数的闭包。