[英]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"]
我认为,基于下面的示例,使我感到惊讶的是,只要提供给谓词的两个连续元素的谓词评估为True
, groupBy
拆分一个列表。 但是在上面的第二个示例中,它在每个元素上拆分了列表,但是谓词应评估为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 isAlphaNum
为True
,它将字符添加到当前序列中。 因此,如果我们评估"t "
, const isAlphaNum
,它将评估为False
, groupBy
将开始一个新的小组。
因此,由于只有一个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
所有元素。 ys
是span
构造的2元组的第一个元素。
span :: (a -> Bool) -> [a] -> ([a],[a])
构造一个2元组,其中第一个元素是满足谓词的列表中最长的前缀。是eq x
因此只要eq xy
(带有y
的元素)成立,我们就继续向组中添加元素。
使用列表ys
的其余部分,我们构造一个新的组,直到输入完全用尽。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.