无法理解currying

时间:2018-07-26 11:13:46

标签: haskell

从理论上讲,我理解什么是curring,但实际上我对ghci中得到的结果感到困惑。

让我们看下面的例子。首先,这是我将要使用的类型。

Prelude> :t f
f :: a -> a -> a -> a

Prelude> :t x
x :: char

Prelude> :t y
y :: char -> char

Prelude> :t z
z :: char -> char -> char

通过执行以下操作,您可以向我解释如何获得这些类型?

Prelude> :t f x
f x :: a -> a -> a

Prelude> :t f y
f y :: (char -> char) -> (char -> char) -> char -> char

Prelude> :t f z
f z
  :: (char -> char -> char)
     -> (char -> char -> char) -> char -> char -> char

2 个答案:

答案 0 :(得分:6)

  

注意char作为类型参数,不是 Char角色。由于它以小写字母开头,因此它是一个类型参数。因此x的类型也是x :: b

Haskell中的一个函数精确地 一个参数。如果有人写道:

f :: a -> a -> a -> a

这实际上是以下简称:

f :: a -> (a -> (a -> a))

因此f接受类型为a的参数,并返回类型为a -> (a -> a)的函数。

f x :: a -> a -> a

如果我们想导出f x的类型,我们可以看到:

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

由于x是具有f作为函数的函数应用程序的参数,因此这意味着xb)的类型应与{函数参数的类型(a)。因此,这意味着a ~ bab的类型相同)。

结果的类型是函数输出的类型,因此为a -> (a -> a)b -> (b -> b)。但是由于b的含义并不比a更具体,所以两者都很好。

a -> (a -> a)的详细表达形式为a -> a -> a

f y :: (b -> b) -> (b -> b) -> b -> b

那么f y呢?作为成分,我们有:

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

由于y是带有f的函数应用程序的参数,因此yb -> b)的类型与a相同,因此也就是说a ~ (b -> b)

输出类型因此是:

f y :: a -> (a -> a)

或当我们转换时:

f y :: (b -> b) -> ((b -> b) -> (b -> b))

或更简单:

f y :: (b -> b) -> (b -> b) -> b -> b

f z :: (b -> b -> b) -> (b -> b -> b) -> b -> b -> b

作为配料,我们有:

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

因此,这意味着对于功能应用程序f z,我们拥有a ~ (b -> (b -> b))。结果是f z的类型为:

f z :: a -> (a -> a)

或当我们将a转换为(b -> (b -> b))时:

f z :: (b -> (b -> b)) -> ((b -> (b -> b)) -> (b -> (b -> b)))

或更简单:

f z :: (b -> b -> b) -> (b -> b -> b) -> b -> b -> b

答案 1 :(得分:2)

f :: a -> a -> a -> a

读取为

f :: a -> (a -> a -> a)

表示:f接受参数a并返回函数a -> a -> a。由于a是类型变量,f是多态的,因此类型a将被选择为与f的参数匹配的任何东西,

因此,对于任何可键入的表达式w,表达式f w具有类型

(type of w) -> (type of w) -> (type of w)

这正是问题中提供的所有示例中发生的情况。