我有点困惑于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取a和b,并返回c
或者可以同样有效地解释为
f获取a,并返回一个函数,该函数获取b并返回c
(a -> b -> c) -> b -> a -> c
与a -> 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中唯一有效的观点。