簡體   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