如何部分应用翻转功能



我有点困惑于flip的"部分"应用程序可能会做什么。

由于flip函数的类型为:

flip :: (a -> b -> c) -> b -> a -> c

我们可以在没有括号的情况下写为:

flip :: a -> b -> c -> b -> a -> c

如何仅将其部分应用于第一个参数a?要获得以下类型的函数:

flipa ::     b -> c -> b -> a -> c

或者这没有意义?

例如,如果我有这样的东西:

let foo a b = (Just a, b)
:t foo
> foo:: a -> t -> (Maybe a, t)

部分应用它是有意义的:

let a = foo 1
:t a
a :: t -> (Maybe Integer, t)

这没有意义。签名

f :: a -> b -> c

相当于

f :: a -> (b -> c)

不等同于

f :: (a -> b) -> c

这个约定就是为什么您可以首先在Haskell中部分应用函数的原因。由于所有函数都是默认设置的,因此签名f :: a -> b -> c可以解释为

f取ab,并返回c

或者可以同样有效地解释为

f获取a,并返回一个函数,该函数获取b并返回c

(a -> b -> c) -> b -> a -> ca -> b -> c -> b -> a -> c不同,因为->运算符是右关联的,而不是左关联的。因此,部分应用flip是没有意义的,因为它最初只有一个参数。

此外,您的示例没有多大意义,因为它仍然会生成一个采用a的输出函数,而您可能不想要它。但如果你去掉它,你会得到一个函数,它接受一个一元函数,并产生完全相同的一元函数。所以只需部分应用原始函数,你就完成了。

正如其他人所指出的,类型(a -> b -> c) -> b -> a -> c而不是a -> b -> c -> b -> a -> c相同。

然而,它(a -> b -> c) -> (b -> a -> c)相同。

这表明flip是一个以单个参数为输入的函数,因此不能部分应用*。


*:从flip返回类型为b -> a -> c的函数的角度来看,这不是Haskell中唯一有效的观点。

最新更新