4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

リストに `sequence` を適用する、とは

Last updated at Posted at 2015-03-25

リストに sequence を適用してみた結果に混乱したので整理しておく。

sequence [[1], [2], [3]] -- [[1,2,3]]

はて、果たして、sequence 関数は何をやっているんだろう。リスト内のリストを結合するだけ?

関数の定義

-- | Evaluate each action in the sequence from left to right,
-- 
and collect the results.
sequence       :: Monad m => [m a] -> m [a] 
{-# INLINE sequence #-}
sequence ms = foldr k (return []) ms
            where
              k m m' = do { x <- m; xs <- m'; return (x:xs) }

instance  Monad Maybe  where
    (Just x) >>= k      = k x
    Nothing  >>= _      = Nothing

    (Just _) >>  k      = k
    Nothing  >>  _      = Nothing

    return              = Just
    fail _              = Nothing

ここで局所関数 km a[m a] をとって m [a] を返す関数であることがわかる。この操作を使って、foldr で畳み込むのが sequence ということになる。

対象が Maybe モナドの場合、次のような結果となりわかりやすい。失敗するかもしれない文脈 を除いた値をリストにしている。

sequence [Just 5, Just 100] -- Just [5,100]
sequence [Just 5, Nothing, Just 100] -- Nothing ( Nothing から値を取ろうとして fail が呼ばれる )

リストモナドの場合、例えばこのようになる。

sequence [[1], [2], [3]] -- [[1,2,3]]

sequence ["abc", "ABC"] -- ["aA","aB","aC","bA","bB","bC","cA","cB","cC"]

sequence [ "ab", "", "ef"] -- [] ( 空リストから要素を取ろうとして fail が呼ばれる )

そう、リストモナドの文脈は 非決定性計算 なので、その文脈を維持して外側のリスト内の各要素を後ろから結合することになる。ゆえに、外側のリスト内の各要素(これもリスト)の要素数を掛け合わせた分だけ、結合した結果がたくさん出来上がる。

外側のリスト内の各要素の要素数が、それぞれ 1 なら、結合した結果がひとつだけできる。これで冒頭のはてなが消えた。

ちなみに、リスト内包表記だと次のような感じで同じように書ける。

[[x,y] | x <- "abc", y <- "ABC"] -- ["aA","aB","aC","bA","bB","bC","cA","cB","cC"]

えっと・・

整理していたら、当たり前のような気がしてきた。

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?