web-dev-qa-db-ja.com

Haskellで2つのリストをマージする

Haskellで2つのリストをマージする方法がわかりません次のように

INPUT:  [1,2,3,4,5] [11,12,13,14]

OUTPUT: [1,11,2,12,3,13,4,14,5]
24
bogatyrjov
merge :: [a] -> [a] -> [a]
merge xs     []     = xs
merge []     ys     = ys
merge (x:xs) (y:ys) = x : y : merge xs ys
43
andri

マージのレイジーバージョンを提案したいと思います。

merge [] ys = ys
merge (x:xs) ys = x:merge ys xs

1つの使用例として、最近のSO 組み合わせの遅延生成 に関する質問を確認できます。
受け入れられた回答のバージョンは、2番目の引数で不必要に厳格であり、それがここで改善されています。

57
Daniel Velkov

では、なぜ単純な(concat。transpose)では「十分ではない」と思いますか?私はあなたが次のようなことを試したことを想定しています:

merge :: [[a]] -> [a]
merge = concat . transpose

merge2 :: [a] -> [a] -> [a]
merge2 l r = merge [l,r]

したがって、明示的な再帰を回避でき(最初の回答と比較して)、2番目の回答よりも簡単です。それで、欠点は何ですか?

23
Ed'ka

編集:エドカの回答とコメントをご覧ください!

別の可能性:

merge xs ys = concatMap (\(x,y) -> [x,y]) (Zip xs ys)

または、Applicativeが好きな場合:

merge xs ys = concat $ getZipList $ (\x y -> [x,y]) <$> ZipList xs <*> ZipList ys
6
danlei

確かに展開のケース:

interleave :: [a] -> [a] -> [a]
interleave = curry $ unfoldr g
  where
    g ([], [])   = Nothing
    g ([], (y:ys)) = Just (y, (ys, []))
    g (x:xs, ys) = Just (x, (ys, xs))
4
idontgetoutmuch