繁体   English   中英

Haskell groupBy函数:它是如何工作的?

[英]Haskell groupBy function: How exactly does it work?

我遇到以下行为:

ghci :m +Data.List

ghci> groupBy (\x y -> succ x == y) [1..6]
[[1,2], [3,4], [5,6]]
ghci> groupBy (\x y -> succ x /= y) [1..6]
[[1], [2], [3], [4], [5], [6]]

ghci :m +Data.Char   -- just a test to verify that nothing is broken with my ghc

ghci> groupBy (const isAlphaNum) "split this"
["split"," this"]

我认为,基于下面的示例,使我感到惊讶的是,只要提供给谓词的两个连续元素的谓词评估为TruegroupBy拆分一个列表。 但是在上面的第二个示例中,它在每个元素上拆分了列表,但是谓词应评估为False 我也假设了它在Haskell中的工作原理,所以每个人都理解我认为它是如何工作的:

groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy p l@(x:y:ys)
  | p x y     = (x:y:(head l)) ++ (tail l)       -- assuming l has a tail, unwilling to
  | otherwise = [x] ++ (y:(head l)) ++ (tail l)  -- to debug this right now, I guess you
groupBy _ [x] = [[x]]                            -- already got the hang of it ;)

得出的结论是,它的工作原理有些不同。 所以我的问题是,该功能实际上如何工作?

但是在上面的第二个示例中,它在每个元素上拆分了列表,但是谓词应评估为False

在第二个示例中, 它还评估每两个连续的元素。 它起作用的函数是const isAlphaNum 所以这意味着类型是:

const isAlphaNum :: b -> Char -> Bool

因此,它以组的开头和元素调用该函数,但是仅考虑第二个元素

因此,如果我们用以下方式调用它: groupBy (const isAlphaNum) "split this" ,它将评估:

succs   2nd    const isAlphaNum
-------------------------------
"sp"    'p'    True
"sl"    'l'    True
"si"    'i'    True
"st"    't'    True
"s "    ' '    False
" t"    't'    True
" h"    'h'    True
" i"    'i'    True
" s"    's'    True

每次const isAlphaNumTrue ,它将字符添加到当前序列中。 因此,如果我们评估"t "const isAlphaNum ,它将评估为FalsegroupBy将开始一个新的小组。

因此,由于只有一个False因此在这里我们构造了两个组。

如果我们分析函数源代码,我们也可以获得此结果:

 groupBy :: (a -> a -> Bool) -> [a] -> [[a]] groupBy _ [] = [] groupBy eq (x:xs) = (x:ys) : groupBy eq zs where (ys,zs) = span (eq x) xs 

因此,如果给定列表为空,则groupBy将返回空列表。 如果它不是一个空列表(x:xs)那么我们将构建一个新序列。 该序列以x开头,并且还包含ys所有元素。 ysspan构造的2元组的第一个元素。

span :: (a -> Bool) -> [a] -> ([a],[a])构造一个2元组,其中第一个元素是满足谓词的列表中最长的前缀。是eq x因此只要eq xy (带有y的元素)成立,我们就继续向组中添加元素。

使用列表ys的其余部分,我们构造一个新的组,直到输入完全用尽。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM