1
0

More than 3 years have passed since last update.

Haskell ArrowApplyからMonadを導出する

Last updated at Posted at 2020-10-24

ArrowApplyはMonadと等価だという話を聞いたので、実際にArrowApplyからMonadを導出してみました。

標準ライブラリ中にはArrowMonadという型が定義されていますが、Arrow型の第一型引数が()に束縛されています。

ArrowMonad
newtype ArrowMonad a b = ArrowMonad (a () b)
forall a. Arrow a => instance Functor (ArrowMonad a)
forall a. Arrow a => instance Applicative (ArrowMonad a)
forall a. ArrowApply a => instance Monad (ArrowMonad a)

今回はこの束縛をなくし、多相性を完全に保ったままMonadを導出します。
すなわち、

ArrowMonadExt
newtype ArrowMonadExt a b c =
    ArrowMonadExt { runArrowMonadExt :: (a b c) }
forall a b. Arrow a => instance Functor (ArrowMonadExt a b)
forall a b. Arrow a => instance Applicative (ArrowMonadExt a b)
forall a b. ArrowApply a => instance Monad (ArrowMonadExt a b)

を定義します。ArrowMonadの時はインスタンス宣言の型変数が一つだった(forall a.)のに対し、ArrowMonadExtの定義では型変数が二つになっている(forall a b.)点がミソです。

また、クラス制約で示されているように、ArrowApplyが必要になるのはMonadの実装だけです。なので、普通のArrowもFunctorやApplicativeとしては扱えます。

共通ヘッダー

この記事のソースコードをコンパイルするには、各ソースコードの冒頭に以下を追加してください。

{-# LANGUAGE Arrows #-}
import Control.Arrow

ArrowMonadExtの定義

newtype ArrowMonadExt a b c =
    ArrowMonadExt { runArrowMonadExt :: (a b c) }

Functorの定義

instance (Arrow a) => Functor (ArrowMonadExt a b) where
    fmap f (ArrowMonadExt m) = ArrowMonadExt $
        proc b -> do
            c <- m -< b
            returnA -< f c

Applicativeの定義

instance (Arrow a) => Applicative (ArrowMonadExt a b) where
    pure x = ArrowMonadExt $
        proc _ -> returnA -< x

    (ArrowMonadExt l) <*> (ArrowMonadExt m) = ArrowMonadExt $
        proc b -> do
            f <- l -< b
            c <- m -< b
            returnA -< f c

Monadの定義

instance (ArrowApply a) => Monad (ArrowMonadExt a b) where
    (ArrowMonadExt m) >>= k = ArrowMonadExt $
        proc b -> do
            c <- m -< b
            d <- runArrowMonadExt $ k c -<< b
            returnA -< d

P.S

多相性を完全に保ったままMonadを導出します。

と書きましたが、結局ArrowMonadExt a bをMonadとして定義しているので、今回の定義とArrowMonadは本質的に同じです。つまり、事前にArrowの入力を()として固定しているか、インスタンス定義時に型変数として固定するかの違いがあるだけで、やっていることは変わりません。

1
0
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
1
0