use*_*628 3 haskell currying type-signature
我之前检查了一个帖子,似乎明白了.我知道
f :: a -> b -> c
Run Code Online (Sandbox Code Playgroud)
是咖喱的形式
g :: (a, b) -> c
Run Code Online (Sandbox Code Playgroud)
但由于类型签名长于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
Run Code Online (Sandbox Code Playgroud)
是(a -> b -> b)和[b]输入和输出?那么中间剩下的是什么?
Wil*_*sem 11
从概念上讲,Haskell中的函数总是只有一个参数.事实上,实际上签名:
myscanr :: (a -> b -> b ) -> b -> [a] -> [b]
Run Code Online (Sandbox Code Playgroud)
是短的:
myscanr :: (a -> (b -> b)) -> (b -> ([a] -> [b]))
Run Code Online (Sandbox Code Playgroud)
所以总有一个参数,但结果也可以是一个函数,然后我们可以为该函数提供一个参数来获取一个值或另一个结果,所以这是某种"链接".
您可以将它与Python之类的编程语言进行比较,而不是拥有一个接受多个参数的函数,它每次都接受一个参数.例如:
# python
def add(x):
def addx(y):
return x + y
return addxRun Code Online (Sandbox Code Playgroud)
所以这里我们有一个功能add.我们可以用一个参数调用它x.如果我们这样做,例如x=4,那么它将返回另一个函数(其中x是作用域).只有当我们用一个参数(例如y=3)调用该函数时,我们才得到结果,如:
>>> add(4)
<function add.<locals>.addx at 0x7f1c519e7b70>
>>> add(4)(3)
7
Run Code Online (Sandbox Code Playgroud)
那么在Haskell中,这个模型是标准的:每个函数只接受一个参数.但既然如此,语法可以改进.((myscanr((+)))(0))([1, 4, 2, 5])我们可以编写myscanr (+) 0 [1, 4, 2, 5],而不是必须编写,Haskell将自动将其解释为具有myscanras函数和(+)参数的函数调用,另一个函数调用as函数作为前一个调用的结果并0作为参数,然后另一个函数调用as使用[1, 4, 2, 5]as参数作为前一次调用的结果.
从语法上看,它看起来有点像我们用三个参数调用,可以说是(a -> b -> b),b并且[a]是" 三个参数 " 的类型.但严格来说,这是错误的.
要从更常见的视图中考虑这一点,其中函数可以有多个参数,签名中的最后一个类型是返回类型.之前的一切都是参数的类型.
在此示例中,您的参数类型是(a -> b -> b),b和[a]:一个函数接受a a和a b并返回a b,a b和as 列表.
返回类型是签名中的最后一种类型[b]:bs 的列表.