foldl1,foldr1,scanl1, scanr1

HaskellRuby の [a, b, c].join(x) と同等のことをするには intersperse が便利。

> concat $ Data.List.intersperse "-" ["abc", "def", "ghi"] -- > "abc-def-ghi"

-- intersperse を自分で作るとこんな感じ。
intersperse' :: a -> [a] -> [a]
intersperse' _ [x] = [x]
intersperse' s (x:xs) = x:s:intersperse' s xs

Haskellの駄目な使い方 / 文字列処言語間理比較表で foldl1,foldr1 でも OK なのを知った。

> foldl1 (\a b -> a ++ "-" ++ b) ["abc", "def", "ghi"] -- > "abc-def-ghi"

> foldr1 (\a b -> a ++ "-" ++ b) ["abc", "def", "ghi"] -- > "abc-def-ghi"

foldl,foldr と foldl1,foldr1 の違いは初期値にリストの値を用いていること。

> foldl (\a b -> a ++ "-" ++ b) [] ["abc", "def", "ghi"] -- > "-abc-def-ghi"
> foldr (\a b -> a ++ "-" ++ b) [] ["abc", "def", "ghi"] -- >  "abc-def-ghi-"

> foldl (\a b -> a ++ "-" ++ b) "start" ["abc", "def", "ghi"] -- > "start-abc-def-ghi"
> foldr (\a b -> a ++ "-" ++ b) "start" ["abc", "def", "ghi"] -- > "abc-def-ghi-start"

scan* を使うと動きを理解しやすい

> scanl (\a b -> a ++ "-" ++ b) "start" ["abc", "def", "ghi"] 
-- > ["start","start-abc","start-abc-def","start-abc-def-ghi"]

> scanr (\a b -> a ++ "-" ++ b) "start" ["abc", "def", "ghi"] 
-- > ["abc-def-ghi-start","def-ghi-start","ghi-start","start"]

> scanl1 (\a b -> a ++ "-" ++ b) ["abc", "def", "ghi"] 
-- > ["abc","abc-def","abc-def-ghi"]

> scanr1 (\a b -> a ++ "-" ++ b) ["abc", "def", "ghi"] 
-- > ["abc-def-ghi","def-ghi","ghi"]