動機
次のF
の形をしたMonad
について考えたかった。
M :: Type
E :: Type
data F a = F M (E -> a)
特に、このようなMonad F
を定めるようなM, E
上の代数的構造を明らかにしたかった。
例えば、Writer m a ~ (m, a)
のMonad
のインスタンスには
m
上のモノイドが1対1に対応するし、
Reader e a ~ (e -> a)
は一意な方法でMonad
になるが、これには
e
上の唯一の”余モノイド”(const () :: e -> (), join (,) :: e -> (e,e))
が対応する。
こんな感じで、Monad F
に対応する代数は何かを考えていた。
が、何日かトライしたもののこれは相当難しい感じがするので、
まずはApplicative F
に何が対応するのかから考えてみた。
Applicative F の構造
ここから、以下の変数が唐突に出てきたら、暗に”任意のx
について…“等が挿入されていると思ってほしい。
z :: M
x, y,f :: E -> a
g :: E -> b
h :: E -> c
まず、pure :: a -> F a
は、次の形しかありえないことを確認しておく。
mPure :: M
pure a = F mPure (const a)
また、Applicative
のインスタンスは、次のprod
を与えても決まる。
prod :: F a -> F b -> F (a,b)
= liftA2 (,) prod
M
とE
に関する関数(<>) :: M -> M -> M
とd :: M -> M -> E -> (E, E)
が、
prod
の実装と1対1に対応する。
F x f) (F y g) = F (x <> y) ((f *** g) . d x y)
prod (
<> y = case prod (F x id) (F y id) of
x F z _ -> z
= case prod (F x id) (F y id) of
d x y F _ k -> k
Applicative
則を満たすためにmPure
, <>
, d
に必要な制約を書き出せば、(mPure, <>) :: (M, M -> M -> M)
がM
上のモノイドを定めることがわかり、さらにd
についても条件を得られる。
-- 右単位
-- 正確なHaskellではないが mPure = 1 と略記する
F (x,f)) (pure b) = (,b) <$> F (x, f)
prod (F (x,f)) (pure b)
prod (= F (x <> 1, (f *** const b) . d x 1)
= (,b) . F (x,f)
<> 1 = x -- (M-unitR)
x fst . d x 1 = id
1 = id &&& dl x -- (d-unitR)
d x -- ここで dl :: M -> E -> E はある関数
-- 同様に左単位
1 <> x = x -- (M-unitL)
snd . d 1 x = id
1 x = dr x &&& id -- (d-unitL)
d -- ここで dr :: M -> E -> E はある関数
-- Applicativeの結合法則
-- 結合法則:
`prod` u) `prod` v
(t = assoc $ t `prod` (u `prod` v)
LHS)
(= F (x <> y, f *** g . d x y) `prod` v
= F ((x <> y) <> z, (f *** g . d x y) *** h . d (x <> y) z)
= F ((x <> y) <> z,
*** g) . second h . first (d x y) . d (x <> y) z)
first (f = F ((x <> y) <> z,
*** g) *** h . first (d x y) . d (x <> y) z)
(f RHS)
(= ...(omit)...
= F (x <> (y <> z),
. f *** (g *** h) . second (d y z) . d x (y <> z))
assoc = F (x <> (y <> z),
*** g) *** h . assoc . second (d y z) . d x (y <> z))
(f
<> y) <> z = x <> (y <> z) -- (M-assoc)
(x . d (x <> y) z
first (d x y) = assoc . second (d y z) . d x (y <> z) -- (d-assoc)
(M-unitR), (M-unitL), (M-assoc)はモノイド則そのものである。
一方でd
に関する法則はあまり明らかでない。
これらの法則はむしろ図に書いたほうがわかりやすい。
| |
---+--- +--*--+
d 1 x === | |
-+---+- --+-- |
| | dr x |
| | --+-- |
| | | |
============================================================
| |
---+--- +--*--+
d x 1 === | |
-+---+- | --+--
| | | dl x
| | | --+--
| | | |
============================================================
| |
-------+------- -------+-------
d (x <> y) z d x (y <> z)
-+-----------+- -+-----------+-
| | | |
---+--- | === | ---+---
d x y | | d y z
-+---+- | | -+---+-
| | | | | |
具体例を調べる
Applicativeの具体例を挙げて、ここまで述べた法則が満たされていることを確認していく。
もっとも単純には、Compose (Writer M) (Reader E)
と同じ
Applicative
のインスタンスが考えられる。これは、
= \i -> (i,i) d _ _
とした場合に相当する。この定義においてd
に関する各法則が成り立つことを確認するのは、
式(d-unitL),etc. を使っても簡単だが、
d _ _
が「入力をただコピーする」ことを図で表した
| |
---+--- |
d _ _ === +-*-+
-+---+- | |
| | | |
を上の3図式に当てはめれば、法則が成り立っていることは自明である。
また、M = E -> E
であるとき、
自然同型 F x ~ (E -> E, E -> x) ~ E -> (E, x) ~ State E x
が得られるが、State E
はMonad
であり、もちろんApplicative
でもあるので、
F x
がApplicative
として得られたことになる。このとき、d
は
d x _ = \i -> (i, x i)
である。このとき、M
上のモノイド演算としては、mempty = id
および
x <> y = x >>> y = y . x
が使われている。
モノイド作用によるApplicative
State E
と同型になるケースとの中間例として、
M
がE
上にモノイド作用を持つ場合というものを考えることができる。
モノイドM
のE
上への(右)モノイド作用(◁) :: E -> M -> E
は
1 = i
i ◁ = i ◁ (x <> y) (i ◁ x) ◁ y
を満たす関数である。モノイド作用◁
を用いて、
= \i -> (i, i ◁ x) d x _
と書ける場合、これはApplicative
則を満たす。上記の定義を図に書くと、
| |
| +--*---+
---+--- | |
d x y === | ----+---
-+---+- | (◁ x)
| | | ----+---
| | | |
となる。法則を表す3図式に当てはめれば、
| | |
| +--*---+ +--*--+
---+--- | | | |
d 1 x === | ----+--- === --+-- |
-+---+- | (◁ 1) dr x |
| | | ----+--- --+-- |
| | | | | |
(モノイド作用であるから(◁ 1)=idであり、dr x = idとおけばよい。)
============================================================
| | |
| +--*---+ +--*--+
---+--- | | | |
d x 1 === | ----+--- === | --+--
-+---+- | (◁ x) | dl x
| | | ----+--- | --+--
| | | | | |
(dl x = (◁ x) とおけばよい)
============================================================
| |
-------+------- -------+-------
d (x <> y) z d x (y <> z)
-+-----------+- -+-----------+-
| | | |
---+--- | === | ---+---
d x y | | d y z
-+---+- | | -+---+-
| | | | | |
|| ||
| |
+----*-----+ +--*--+
| | | |
| ------+------ | ---+---
| (◁ (x <> y)) | (◁ x)
| ------+------ | ---+---
+--*--+ | | |
| | | | +-*---+
| ---+--- | | | |
| (◁ x) | | | ---+---
| ---+--- | | | (◁ y)
| | | | | ---+---
| | | | | |
(モノイド作用の結合法則から両辺は等しい)
今考えたものは右モノイド作用であるが、左モノイド作用を考えることもできて、
左モノイド作用 (▷) :: M -> E -> E
は次式を満たす。
1 ▷ i = i
= (x <> y) ▷ i x ▷ (y ▷ i)
これを用いて、
= \i -> (y ▷ i, i) d _ y
と書ける場合もApplicative
則を満たす。右作用と同じように図を描くことでこれも確認できる。
さて、右モノイド作用と左モノイド作用の両方が定義されているとき、次のd
を考える。
= \i -> (y ▷ i, i ◁ x) d x y
これは各法則を満たすだろうか?図を書いていくと(AAめっちゃ面倒だったので省略)
= z ▷ (i ◁ x) (z ▷ i) ◁ x
が任意のz,x :: M, i :: E
に対して成り立っているとき、そのときに限り成り立つことがわかる。
これは左右のモノイド作用が可換であることを言っている。
加群の例に倣うなら”E上の(M,M)-両側モノイド作用”とでも呼べばいいだろうか。
具体例を出してみよう。M = E = Int
とし、M
のモノイドはInt
の加法とする。
x ▷ y = x ◁ y = x + y
とすれば、これは左右のモノイド作用を定めており、さらに互いに可換である。
d x y = \i -> (i + y, i + x)
を用いてApplicativeの定義式まで展開してみると、
newtype F x = F (Int, Int -> x)
instance Applicative F where
pure x = F (0, const x)
F (x, f) <*> F (y, g) = F (x + y, \i -> f (i + y) (g (i + x)))
である。こんなApplicativeは見たことさえないし、何かの役に立つのかまったくわからないが、 ともかく両側モノイド作用を使って、新しいApplicativeを量産する方法を手に入れたことになる。
一般論に戻って
しかし、本来の疑問はすべてのApplicativeのインスタンスと対応する代数はなにかということだった。 両側モノイド作用によるApplicative以外にもそのような例があるだろうか?
まだ次の疑問が解決していない。
- 関手
F x ~ (M, E -> x)
に対するすべての可能なApplicativeのインスタンスは、両側モノイド作用によるものか?
多分違うと思うけれども、反例が思いつかない・・・
また、違うなら違うで、もともとの疑問である
- 関手
F x ~ (M, E -> x)
に対するすべての可能なApplicativeのインスタンスは、M, E
に関するどんな代数と対応させられるか?
も考える必要がある。