我是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) 是该功能的论点。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top