私は、パターンマッチングに関して、Haskellリスト内包表記が「内部」でどのように機能するかを理解しようとしています。次のghci出力は、私のポイントを示しています。
Prelude> let myList = [Just 1, Just 2, Nothing, Just 3]
Prelude> let xs = [x | Just x <- myList]
Prelude> xs
[1,2,3]
Prelude>
ご覧のとおり、「Nothing」をスキップして「Just」の値のみを選択することができます。リストはモナドであり、次のように定義されていることを理解しています(Real World Haskell、ch。14からの出典):
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs)
xs >> f = concat (map (\_ -> f) xs)
fail _ = []
したがって、リスト内包は基本的に、リスト内包で選択されたすべての要素に対してシングルトンリストを作成し、それらを連結します。あるステップでパターン一致が失敗した場合、代わりに「失敗」関数の結果が使用されます。つまり、「Just x」パターンが一致しないため、「concat」が呼び出されるまで[]がプレースホルダーとして使用されます。これが、「何も」がスキップされているように見える理由を説明しています。
私が理解していないのは、Haskellが「失敗」関数を呼び出すことをどのように知っているのかということです。それは「コンパイラの魔法」なのか、それともHaskellで自分で書くことができる機能なのか?次の「選択」関数を記述して、リスト内包表記と同じように機能させることはできますか?
select :: (a -> b) -> [a] -> [b]
select (Just x -> x) myList -- how to prevent the lambda from raising an error?
[1,2,3]