Haskell道 その4
前回からかなり空いてますがHaskellの勉強はゆったりながら続けてますよ。
途中の章はいろいろ飛ばしてファンクターに行きましょう。
ファンクターとは?
ファンクターは文脈を持った箱です。箱の中にある値に文脈を持たせるともいえます。箱なので値を取り出して、加工して、また戻すこともできます。
ファンクターといえば、Maybe型が有名です。
Maybeの定義はこちら。
data Maybe a = Just a | Nothing
ここでの a は箱に入れる値の型です。Java的にはジェネリクス。
Maybe型とは、値に不確実性の文脈を与えます。日本語的には「もしかすると〜かもしれない(失敗していなければ)」という意味です。
ファンクター値に関数を適用
ファンクターの箱の中にある値をファンクター値と呼んだりします。そしてファンクター値に関数に適用するのが fmap です。関数に適用させて得られた値はそのままファンクターに包まれたままです。イメージとしては、箱の中に入れたまま値を関数に適用させる感じです。
試しにMaybeのファンクター値に対して3を掛けてみます。
Prelude> let a = Just 2 Prelude> a Just 2 Prelude> fmap (\x -> x * 3) a Just 6
「2かもしれない」ものに対して3を掛ければ、「6かもしれない」ものになりました。ここで重要なのは文脈が維持されることにあります。
ファンクター則
第一法則「idで写してもファンクター値は同じである」
id は 与えられた引数をそのまま返す関数です。Maybeで示すと以下が成り立つ。
fmap id (Just 3) == id (Just 3)
第二法則「gの次にfでファンクター値を写したものと、合成関数f・gでファンクター値を写したものは同じである」
Maybeで示すと以下が成り立つ。
fmap f $ fmap g (Just 3) == fmap (f . g) (Just 3)
まとめると「箱から値を取り出して、与えられた関数を適用して、また戻す」という動作のみが fmap で実装されていればいいことになる。
与えられた関数を無視したり、関数適用以外の余計なことはしないということですね。