我之前检查过post并且似乎明白了。我知道
f :: a -> b -> c
是
的咖喱形式g :: (a, b) -> c
但是由于类型签名比2个箭头长,我感到很困惑。
myscanr :: (a -> b -> b) -> b -> [a] -> [b]
myscanr op z [] = [z]
myscanr op z (x:xs) = op x (head qs) : qs
where
qs = myscanr op z xs
输入和输出是(a -> b -> b)
和[b]
吗?那么中间的其余部分是什么?
答案 0 :(得分:11)
从概念上讲,Haskell中的函数始终只有一个参数。事实上,实际上是签名:
myscanr :: (a -> b -> b ) -> b -> [a] -> [b]
简称:
myscanr :: (a -> (b -> b)) -> (b -> ([a] -> [b]))
所以总有一个参数,但结果也可以是函数,然后我们可以为该函数提供一个参数来获取一个值,或者另一个结果,所以这是某种"链接"。
您可以将它与Python之类的编程语言进行比较,而不是拥有一个接受多个参数的函数,它每次都接受一个参数。例如:
# python
def add(x):
def addx(y):
return x + y
return addx
所以这里我们有一个函数add
。我们可以使用单个参数x
来调用它。如果我们这样做,例如x=4
,那么它将返回另一个函数(其中x
作用域)。只有当我们用一个参数(例如y=3
)调用该函数时,我们才得到结果,如:
>>> add(4)
<function add.<locals>.addx at 0x7f1c519e7b70>
>>> add(4)(3)
7
在Haskell中,这个模型是标准:每个函数只接受一个参数。但既然如此,语法可以改进。我们可以编写((myscanr((+)))(0))([1, 4, 2, 5])
而不必编写myscanr (+) 0 [1, 4, 2, 5]
,而Haskell会自动将其解释为函数调用,myscanr
为函数,(+)
为参数,另一个函数调用使用前一个调用的结果和0
作为参数的函数,然后使用[1, 4, 2, 5]
作为参数,使用as函数调用另一个函数调用。
从语法上讲,它看起来有点像我们使用三个参数进行调用,可以说(a -> b -> b)
,b
和[a]
是&#34; 三个参数&#34;的类型。但严格来说,这是错误的。
答案 1 :(得分:5)
从更常见的视图中考虑这一点,其中函数可以有多个参数,签名中的最后一个类型是返回类型。之前的一切都是参数的类型。
在此示例中,您的参数类型为(a -> b -> b)
,b
和[a]
:一个函数,其中包含a
和b
并返回{ {1}},b
和b
s。
返回类型是签名a
中的最后一种类型:[b]
的列表。
答案 2 :(得分:4)
将类型签名读作转换... -> to
,其中&#34;位于中间&#34;是争论。
例如。 myscanr :: (a -> b -> b) -> b -> [a] -> [b]
&#34;&#34;功能(a -> b -> b)
,b
,[a]
列表,并返回b [b]