spanの小ネタ(使い方編)
もあわせてどうぞ.
spanの型は(a -> Bool) -> [a] -> ([a],[a])ですが,これは関数型(function type)ですね.この関数型のコドメインは,[a] -> ([a],[a])という関数型です.spanはこの型の関数を生成する高階関数です.さて,生成される関数は,リストの先頭部分を処理し,その結果と残りの未処理部分とを対にする関数です.
もうすこし,一般化したパターンでは,a -> (b, a)と表現されます.雑なイメージで表現すると「aをすこしずつ消費して,消費して処理した結果bと未消化の残り部分aとを組にする」ということです.組になった残りの部分にまた同じ処理を再帰的に適用するという処理パターンは良く見るパターンです.そうですね,これがanamorphismという再帰パターンです.部分結果をリストに組み上げる処理が,unfoldr :: (a -> Maybe (b, a)) -> a -> [b])です.unfoldr は Data.List モジュールにあります。
これは、つきあがった大きな餅のかたまりから、つぎつぎと一口大の小餅をひねり取って、黄粉まぶして、丸めて、ならべていくイメージです.
spanの典型的な利用例としては,anamorphismの実装が多いようです.というわけで,groupBy :: (a -> a -> Bool) -> [a] -> [[a]]を実装してみましょう.
code:haskell
groupBy eq = unfoldr psi
where
psi [] = Nothing
psi xs@(x:_) = Just (span (eq x) xs)