Haskell で Ruby の [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"]