LoginSignup
15
4

More than 3 years have passed since last update.

[Haskell] FunctorクラスはHask圏からHask圏への関手

Last updated at Posted at 2017-12-11

タイトルは、[Haskell] FunctorクラスはHask圏からHask圏への関手となっていますが、
もっと正確には、[Haskell] FunctorクラスはHask圏からHask圏の部分圏への関手のほうが、より適切かもしれません。

もともとこの記事はHaskellアドベントカレンダー(その3)の、12/14に登録した「とびだせ!Hask圏」という記事の前半部分として書いていたものです。

ただ、その記事がクソ長くなってしまいそうだったので、前半を分離して一つの記事にしたのがこの記事になります。

基本的な用語

圏とは

圏の公理を書こうかと思ったんですが、結構面倒くさいので省略します。
忘れちゃダメなポイントは、

  • すべての対象に恒等射が存在する
  • 射の合成は結合則を満たす

という点です。

Hask圏とは

  • 対象はHaskellの、カインドが*である
  • 射はHaskellの関数
  • 射の始域は関数の引数の型
  • 射の終域は関数の戻り値の型
  • 恒等射はid
  • 射の合成は関数結合 (.)

であるような圏です。

関手とは

圏 C から圏 D への共変関手 F とは、

  • C の任意の対象 X を、 D の対象 F(X) に対応させる。
  • C の任意の射 f : X -> Y を、Dの射 F(f) : F(X) -> F(Y) に対応させる。
  • C の恒等射は、 D の恒等射に対応させる。
  • C の任意の射 f : X -> Y と g : Y -> Z について、F(g ∘ f) = F(g) ∘ F(f) を満たす。

以上をみたすようなもののことです。

最後のはちょっと分かりづらいかもしれませんが、射を合成してから関手で移しても、関手で移してから合成してもおんなじってことです。

Haskell の Functorクラス

HaskellにはFunctorという型クラスがあり、これは関手を表現しています。

では、具体的にどんな圏からどんな圏への関手なのでしょうか?

例:Maybe

代表的なFunctorである Maybe を例にとって考えてみましょう。
Maybeという型コンストラクタのカインドを見てみると

kind
ghci> :kind Maybe
Maybe :: * -> *

というように、カインド*を持つ任意の型を、カインド*を持つ別の型に移すものだとわかります。

具体的には、

kind
ghci> :kind Int
Int :: *
ghci> :kind Maybe Int
Maybe Int :: *

という具合です。

どうやらこれは関手の定義のうちの一つ、「C の任意の対象 X を、 D の対象 F(X) に対応させる」という性質を表現しているようです。

つぎに、fmapという関数について考えてみます。
fmapの型を見てみると

type
ghci> :type fmap
fmap :: Functor f => (a -> b) -> f a -> f b

これは多相的な表現になっていますが、Maybeに限って言えばfmap :: (a -> b) -> (Maybe a -> Maybe b) ということです((->)は右結合なので括弧を補足しました)

この型を見ると、fmapは任意の型の間の関数 f :: a -> b を、fmap f :: Maybe a -> Maybe b に移すものだとわかります。

これは関手の定義のひとつ、「C の任意の射 f : X -> Y を、Dの射 F(f) : F(X) -> F(Y) に対応させる」という性質を表現しているようです。

Maybeの例からわかること

さて、型コンストラクタ Maybe が関手による対象の対応付け、fmap が関手による射の対応付けを表現していることがわかりました。

では、この関手はどんな圏からどんな圏への関手を表現しているのでしょう?
その答えは、関手によって移される前後の「対象」と「」に注目してみるとわかります。

Maybeで移される前 Maybeで移された後
対象 カインド*を持つ型 カインド*を持つ型
関数 関数

この表を見ると、Maybeによって移される前後で両方とも対象が*で射が関数なので、両方ともHask圏であると言えそうです。

(移された後の対象はすべて Maybe a という形をとる型に限られるので、「Hask圏の部分圏」と言ったほうが、より適切かもしれません)

ここではMaybeを例に挙げましたが、他のFunctorでも同じことです。

一般にHaskellのFunctorクラスはHask圏からHask圏への関手を表現していると言えます。

まとめ

タイトルにもなっていますが、

HaskellのFunctorクラスはHask圏からHask圏への関手

ということがわかりました。

15
4
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
15
4