从理论上讲,我理解currying是什么,但实际上我对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
Run Code Online (Sandbox Code Playgroud)
通过以下操作,您能告诉我如何获得这些类型吗?
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
Run Code Online (Sandbox Code Playgroud)
注:该
char类型的参数,是不是一个CharACTER.由于它以小写字母开头,因此它是一个类型参数.x因此x :: b也是这种类型.
Haskell中的函数只有一个参数.如果有人写道:
f :: a -> a -> a -> a
Run Code Online (Sandbox Code Playgroud)
那么这实际上是:
f :: a -> (a -> (a -> a))
Run Code Online (Sandbox Code Playgroud)
所以f接受一个类型的参数a,并返回一个类型的函数a -> (a -> a).
f x :: a -> a -> a如果我们想要派生类型f x,我们可以看到:
f :: a -> (a -> (a -> a))
x :: b
Run Code Online (Sandbox Code Playgroud)
因为x是具有fas函数的函数应用程序的参数,所以它意味着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
Run Code Online (Sandbox Code Playgroud)
由于y是具有功能的应用程序的参数f的类型,y(b -> b)是相同的类型a,这样就意味着a ~ (b -> b).
因此输出类型是:
f y :: a -> (a -> a)
Run Code Online (Sandbox Code Playgroud)
或者当我们转换它时:
f y :: (b -> b) -> ((b -> b) -> (b -> b))
Run Code Online (Sandbox Code Playgroud)
或者更简洁:
f y :: (b -> b) -> (b -> b) -> b -> b
Run Code Online (Sandbox Code Playgroud)
f z :: (b -> b -> b) -> (b -> b -> b) -> b -> b -> b作为我们的成分:
f :: a -> (a -> (a -> a))
z :: b -> (b -> b)
Run Code Online (Sandbox Code Playgroud)
这意味着对于功能应用程序f z,我们就这样了a ~ (b -> (b -> b)).结果是类型f z是:
f z :: a -> (a -> a)
Run Code Online (Sandbox Code Playgroud)
或当我们转换a为(b -> (b -> b)):
f z :: (b -> (b -> b)) -> ((b -> (b -> b)) -> (b -> (b -> b)))
Run Code Online (Sandbox Code Playgroud)
或者更简洁:
f z :: (b -> b -> b) -> (b -> b -> b) -> b -> b -> b
Run Code Online (Sandbox Code Playgroud)