如何部分应用翻转功能?

时间:2012-02-24 15:39:37

标签: haskell

我对翻转的“部分”应用可能会做什么感到有点困惑。

由于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)

3 个答案:

答案 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 -> ca -> 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中唯一有效的观点。