bitterharvest’s diary

A Bitter Harvestは小説の題名。作者は豪州のPeter Yeldham。苦闘の末に勝ちえた偏見からの解放は命との引換になったという悲しい物語

関手―余積をファンクタで実現する

6.8 余積をファンクタで実現する

前回の記事では関手を利用しての積と余積を定義する中で\(Identity\)を用いたが、その詳しい説明はしなかった。そこで、ここでは、まず、データ型\(Identity\)の定義から話を始めよう。関手\(Identity\)の互換図は下図のようになる。
f:id:bitterharvest:20170303080859p:plain
これを参考にしてHaskellで\(Identity\)のデータ型とファンクタを実現すると次のようになる。

data Identity a = Identity a deriving (Eq, Show, Read) 

instance Functor Identity where
  fmap f (Identity a) = Identity (f a)

終対象への写像に似ている関数で、一つの値\(c\)に写像する定数関数\(const\)と呼ばれるものがある。これを下図のように関手として利用してみよう。
f:id:bitterharvest:20170306141445p:plain
\(Const\)のデータ型とファンクタは次のようになる。

data Const c a = Const c deriving (Eq, Show, Read)

instance Functor (Const c) where
  fmap f (Const c) = Const c

少し利用してみよう。

*Main> a = Identity 4
*Main> fmap (*3) a
Identity 12
*Main> fmap (+6) a
Identity 10
*Main> b = Const 3
*Main> fmap (*3) b
Const 3
*Main> fmap (+6) b
Const 3

今得た二つの互換図を左右を逆にして重ねてみよう。
f:id:bitterharvest:20170306141459p:plain
この互換図は定数\(Const \ c\)と値\(Identity \ a\)との余積と見ることができる。しかも、余積はファンクタとしての\(Identity\)と\(Const\)により実現されている。

それでは、\(Const \ c\)を\( ( ) \)で置き換えてみよう。
f:id:bitterharvest:20170306141520p:plain
これも余積である。Haskellは余積を\(Either\)で表していたので、これは\(Either \ (Const \ ()) \ (Identity \ a)\)と書くことができる。

これは何かに似ていないだろうか。\(Maybe\)は値を持たないか値を持つかのいずれかであった。値を持たない場合には\(Nothing\)で表し、持つ場合には\(Just \ a\)で表した。そこで、これを今得た\(Either\)に当てはめてみよう。\(Nothing\)を\(Const \ ( )\)と、\(Just \ a\)を\(Identity \ a\)と考えてみよう。相互に表現法が違うだけで同じものであることが分かる。そこで、\(Either \ (Const \ ()) \ (Identity \ a)\)をタイプを用いて次のように\(Maybe'\)で言い換えてみる。

type Maybe' a = Either (Const () a) (Identity a)

少し利用してみよう。変数のデータ型を定めながらの利用になるが以下の様である。

*Main> a = Identity (3 :: Integer)
*Main> b = Right a :: Maybe' Integer
*Main> c = Const () :: Const () Integer
*Main> d = Left c :: Maybe' Integer
*Main> :t a
a :: Identity Integer
*Main> a
Identity 3
*Main> b
Right (Identity 3)
*Main> c
Const ()
*Main> d
Left (Const ())
*Main> :t a
a :: Identity Integer
*Main> :t b
b :: Maybe' Integer
*Main> :t c
c :: Const () Integer
*Main> :t d
d :: Maybe' Integer
*Main> :i a
a :: Identity Integer 	-- Defined at <interactive>:9:1
*Main> :i b
b :: Maybe' Integer 	-- Defined at <interactive>:10:1
*Main> :i c
c :: Const () Integer 	-- Defined at <interactive>:11:1
*Main> :i d
d :: Maybe' Integer 	-- Defined at <interactive>:12:1

このことからも、\(Maybe\)と\(Either\)は同じ概念を表していることが分かる。沢山のファンクタについて説明してきたが、次は反関手の話をする。