top page > computer > haskell > web_lecture > for_programmer > zip_def.html
更新日:
文責: 重城良国

関数zip, zipWith, unzip

zips.hs

関数zip

動作

ふたつのリストをとってタプルのリストにする。

% ghci
Prelude> zip [0 ..] "hello"
[(0, 'h'), (1, 'e'), (2, 'l'), (3, 'l'), (4, 'o')]

zipRaw, zipU :: [a] -> [b] -> [(a, b)]

生の再帰

zipRaw (x : xs) (y : ys) = (x, y) : zipRaw xs ys
zipRaw _ _ = []

それぞれのリストの先頭の要素から成るタプルをひとつめのリストの残りとふたつめのリストの残りをzipしたものに追加すれば良い。

関数unfoldr

zipU = curry . unfoldr $ \l -> case l of
(x : xs, y : ys) -> Just ((x, y), (xs, ys))
_ -> Nothing

リストのタプルを状態とする。それぞれのリストの先頭を結果とし、それぞれのリストから先頭をけずったものを新しい状態とする。

関数zipWith

動作

2つのリストの各要素を指定した関数で結びつける。

Prelude> zipWith (*) [5, 8, 2, 1] [3 ..]
[15,32,10,6]

zipWithRaw, zipWithU :: (a -> b -> c) -> [a] -> [b] -> [c]

生の再帰

zipWithRaw op (x : xs) (y : ys) = x `op` y : zipWithRaw op xs ys
zipWithRaw _ _ _ = []

関数zipとほぼ同じだ。違いはタプルにまとめるのではなく2引数関数を適用していることだ。

関数unfoldr

zipWithU op = curry . unfoldr $ \l -> case l of
(x : xs, y : ys) -> Just (x `op` y, (xs, ys))
_ -> Nothing

タプルにまとめるのではなく2引数関数を適用している。

関数zipWithによる関数zipの定義

関数zipは関数zipWithを使って次のように定義できる。

zipZW = zipWith (,)

zipWithの第1引数にタプル作成演算子を指定したものがzipだ。

関数unzip

動作

タプルのリストを2つのリストにわける。わけられたリストはタプルにまとめられる。

Prelude> unzip [(3, 8), (9, 5), (4, 2)]
([3,9,4],[8,5,2])

unzipRaw, unzipF :: [(a, b)] -> ([a], [b])

生の再帰

unzipRaw ((x, y) : xys) = (x : xs, y : ys)
where (xs, ys) = unzipRaw xys
unzipRaw _ = ([], [])

リストの残りをunzipしたふたつのリストに先頭の要素をxとyに分けたものをそれぞれ追加する。

関数foldr

unzipF = foldr (\(x, y) (xs, ys) -> (x : xs, y : ys)) ([], [])

関数foldrの第1引数である関数fについて考える。関数fの第1引数はもとのリストの先頭の要素であり第2引数は残りのリストを分けた結果であるふたつのリストである。それぞれの先頭にもとのリストをふたつに分けた結果であるx, yを追加する。

まとめ

関数zip, zipWith, unzipの定義を見た。

「関数unfoldr, dropWhileによる関数filterの定義」へもどる 「関数(++), concat, reverse」へ

正当なCSSです! HTML5 Powered with CSS3 / styling, and Semantics