从理论上讲,我理解什么是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
答案 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
作为函数的函数应用程序的参数,因此这意味着x
(b
)的类型应与{函数参数的类型(a
)。因此,这意味着a ~ b
(a
与b
的类型相同)。
结果的类型是函数输出的类型,因此为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
的函数应用程序的参数,因此y
(b -> 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)
这正是问题中提供的所有示例中发生的情况。