[英]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.