Haskellのモナド

てきとうにぐぐって、なんとなく分かりかけてきたので、簡単なまとめです。

いろいろな分野でモナドと呼ばれるものがありますが、Haskellではただの型クラスです。do記法があるという点以外は特別扱いされていません。do記法はただの糖衣構文なのでモナドの扱いを便利に書けるだけです。

定義は以下のようになっています。

Prelude> :i Monad
type Monad :: (* -> *) -> Constraint
class Applicative m => Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  (>>) :: m a -> m b -> m b
  return :: a -> m a
  {-# MINIMAL (>>=) #-}
        -- Defined in ‘GHC.Base’
instance Monad (Either e) -- Defined in ‘Data.Either’
instance Monad [] -- Defined in ‘GHC.Base’
instance Monad Maybe -- Defined in ‘GHC.Base’
instance Monad IO -- Defined in ‘GHC.Base’
instance Monad ((->) r) -- Defined in ‘GHC.Base’
instance (Monoid a, Monoid b, Monoid c) => Monad ((,,,) a b c)
  -- Defined in ‘GHC.Base’
instance (Monoid a, Monoid b) => Monad ((,,) a b)
  -- Defined in ‘GHC.Base’
instance Monoid a => Monad ((,) a) -- Defined in ‘GHC.Base’

Haskellでは型クラスの実装に型以外の制約は付けられませんから、モナド則に従わない実装も可能です。つまり、HaskellではMonadのInstanceではあるが、圏論的な意味でのモナドではないものが作れます。そのようなものを作っても意味が無いので普通は作りません。Haskellで最初から用意されているモナドインスタンスはモナド則に従っているはずです。つまり、それらのモナドインスタンスの共通点は「型クラスMonadのインスタンスでモナド則に従っているはずである」というだけです。ですので「モナドとはなにか?」に対する答えは圏論的なモナド則の話になるし、「Haskellでの実装はどうなっているのか?」に対しては個別の実装の話になります。

言語的にモナドが特別扱いされているのはdo記法だけです。バインドと呼ばれる>>=演算子はモナドと関数を受け取ってモナドを返しますから、結果と別の関数からさらにモナドを受け取るメソッドチェーンが作れます。これらの性質を使ってdo記法という糖衣構文でメソッドチェーンを簡潔に書ける点がHaskellでのモナドの便利な点です。

コメント

このブログの人気の投稿

五十音配列付き新下駄配列

WSLでの親指シフトはどうやらMozcで実現可能と気がつくまで

親指シフト新下駄配列の可能性