有多少个参数占据了Haskell的foldr函数?
题
我是Haskell的新手,我正在阅读这本书 “现实世界哈斯克尔”. 。在本书的第4章中,作者要求作为一种练习,以使用折叠来重写组函数。这本书的读者之一(Octavian Voicu)给出了以下解决方案:
theCoolGroupBy :: (a -> a -> Bool) -> [a] -> [[a]]
theCoolGroupBy eq xs = tail $ foldr step (\_ -> [[]]) xs $ (\_ -> False)
where step x acc = \p -> if p x then rest p else []:rest (eq x)
where rest q = let y:ys = acc q in (x:y):ys
我的问题很简单: 我知道foldr需要3个参数:一个函数,一个初始值和列表。但是在代码foldr的第二行中,需要4个参数。 为什么会发生这种情况?谢谢你。
解决方案
斯科特的答案是正确的, foldr
是一个功能,所以这就是为什么 foldr
需要4个参数。这 foldr
功能确实需要3个参数(函数,基础,列表):
*Main> :type foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
我将在这里举一个不那么复杂的示例:
inc :: Int -> (Int -> Int)
inc v = \x -> x + v
test = inc 2 40 -- output of test is 42
在上述代码中, inc
有一个论点, v
, ,并返回一个通过 v
.
如下所示,返回类型 inc 2
是一个函数,因此可以简单地添加其参数:
*Main> :type inc
inc :: Int -> Int -> Int
*Main> :type inc 2
inc 2 :: Int -> Int
*Main> :type inc 2 40
inc 2 40 :: Int
括号可以用来强调返回值是一个函数,但在功能上与上述代码相同:
*Main> (inc 2) 40
42
PS:我是原始评论的作者:)
其他提示
在这种情况下,我认为最好查看 foldr
:
foldr :: (a -> b -> b) -> b -> [a] -> b
为了将其与我们具有的表达式匹配(为了清楚起见,附加括号):
(foldr step (\_ -> [[]]) xs) (\_ -> False)
第二个论点 foldr
与结果相同。在这种情况下,第二个参数是一个函数。在这种情况下,这意味着 foldr
带有3个参数的表达将是一个函数。
您认为是foldr函数的第四个参数也可以被认为是foldr结果的第一个参数!
Haskell中的所有功能都只有一个论点。当我们具有类型的功能时 a -> b -> c
, ,这只是写作的较短方法 a -> (b -> c)
, ,即一个函数,该函数采用一个参数并产生一个函数,该函数采用另一个参数。看 咖喱 了解更多信息。
在这种情况下,请参见 @sepp2k的答案。 foldr
产生一个函数,需要另一个(“第四”)参数。
在这种情况下 foldr
用于构建功能。 (\_ -> False)
是该功能的论点。