我对翻转的“部分”应用可能会做什么感到有点困惑。
由于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)
答案 0 :(得分:19)
没有意义。签名
f :: a -> b -> c
相当于
f :: a -> (b -> c)
并不等同于
f :: (a -> b) -> c
这个约定就是为什么你可以在Haskell中部分应用函数的原因。由于默认情况下所有函数都是curry,因此签名f :: a -> b -> c
可以解释为
f需要 a 和 b ,并返回 c
或同样可以有效地解释为
f接受 a ,并返回一个 b 并返回 c
的函数
答案 1 :(得分:7)
(a -> b -> c) -> b -> a -> c
与a -> b -> c -> b -> a -> c
不同,因为->
运算符是右关联运算符,而不是左关联运算符。因此,部分应用flip
是没有意义的,因为它首先只有一个参数。
另外,你的例子没有多大意义,因为它仍然会产生一个a
的输出函数,你可能不想要它。但是如果你把它拿出来,你会得到一个函数,它具有一元函数并产生完全相同的一元函数,因此只需部分应用原始函数即可。
答案 2 :(得分:3)
正如其他人所说,(a -> b -> c) -> b -> a -> c
类型 与a -> b -> c -> b -> a -> c
相同。
但是, 与(a -> b -> c) -> (b -> a -> c)
相同。
这表明flip
是一个函数,它将一个参数作为输入,因此无法部分应用*。
*:从flip
的角度来看,返回类型b -> a -> c
的函数,它不是Haskell中唯一有效的观点。