圏論とIOモナド

オブジェクトとして集合X={1}、射としてX->Xの関数f(x)=xひとつだけを持つ圏は、圏や関手のイメージを掴むのに便利だった。しかし、もう少し複雑な圏にも挑戦しよう。

オブジェクトとして、集合X={1,2}と集合Y={a,b}という二つの集合をとり、射として X->Yの関数 id, f の二つの関数を持つ圏 C を考えてみよう。この場合 Hom(X,Y)={id, f} である。このとき、id, f をそれぞれ次のように定義する。

id(1)=a, id(2)=b
f(1)=b, f(2)=a

これが圏になるためには、id と f の合成 * が定義されている必要があるが、id も f も共に X->Y 型の関数であり、このままでは合成写像を作ることができない。そこで、技巧的だが関数と関数の合成をする演算子 * をつぎのように定めることにする。

f * g は、gの値が a の時は、f の引数として1を渡し、gの値が b の時は、f の引数として2を渡す。

このように定義すると、Hom(X,Y)の関数の合成ができて、たとえば、

(f*f)(1)=f(*f(1))=f(*b)=f(2)=a

のように合成関数を作ることができる。また、このように演算子 * を定めると、次の結合法則が成り立つ。

(h * g) * f = h * (g * f)

また、

(id * f) (1) = id * (f(1)) = id *(b) = id (2) = b = f(1) から id * f = f が、

f * id (1) = f * a = f(1) から f * id = f がわかる。

これらのことから C が圏であることが分かる。

ところで、圏 Cの事情はIOモナドに通じるものがある。いま、集合XをHaskellの通常の型のデータ全てからなる集合、集合YをIO型のデータからなる集合と考えると、X->Y の関数の全てからなる集合について、演算子 >>= によって結合法則、

(h x >>= g ) >>= f = h x >>= (g >>= f)

が成立し、return 関数についてみると、

return x >>= f = f x, f x >>= return = f x

となって、return 関数がIOモナドの単位元になっていることが分かる。したがって、IOモナドは圏の条件を満たしている事が分かる。「引数ひとつをとり、IO型を返す」という単純なルールは、その関数がIOモナドの関数であるという条件を満たしている事を理論的にも保証しているのかもしれない。

圏論を理解することがHaskellを使うための必須条件なら、この便利なプログラム言語を使うことのできる人は非常に限られてくるだろう。しかし、「引数一つをとり、IO型を返す」という単純なルールにしたがってコーディングするだけでIOモナドが使いこなせるのなら、これを使わないという手はない。
[PR]
by tnomura9 | 2010-10-24 23:18 | Haskell | Comments(0)
<< モナドのKleisli圏 圏論 >>