Category型クラス
概要
Hask圏では、対象を型、射を関数とみなしていたが、 あとから見れば順序が逆だが、普通のHaskellerはHask圏の存在から知るのでこういう説明になるmrsekut.icon
inputをoutputに「どのように変換するか」がインスタンスとなるので、
Categoryのインスタンスが圏
Categoryそのものは「圏の定義」なので、圏よりも上の次元の概念である
例えば、->で構成されたCategoryが、Hask圏である つまり、Hask圏は、「関数の圏」である
Hask圏は、Categoryで定義できる圏の部分圏になっている? 直感的にはそう思えるが、確認はしていないmrsekut.icon
定義
射の視点からの圏の定義なので、「合成」と「恒等射」のみ定義すれば十分mrsekut.icon code:hs
class Category cat where
id :: cat a a -- 恒等射
(.) :: cat b c -> cat a b -> cat a c -- 合成
a型の値からb型の値を生み出すことを表す
便利関数
Control.Categoryモジュール内に定義されている
code:hs
-- 右から左への合成
(<<<) :: Category h => h b c -> h a b -> h a c
(<<<) = (.)
-- 左から右への合成
(>>>) :: Category h => h a b -> h b c -> h a c
(>>>) = flip (.) -- もしくは、f >>> g = g.f
インスタンスの例
普通の関数
code:hs
instance Category (->) where
id = id -- 実際は、GHC.Base.id
(.) = (.) -- 実際は、(GCH.Base..)
関数名が同じだとエラーになるので、実際はこんなふうに定義されている code:hs
instance Monad m => Category (Kleisli m) where
id :: a -> m a
id = return
(.) :: (b -> m c) -> (a -> m b) -> (a -> m c)
g . f = g <=< f
cat a bがa -> m bになるような型コンストラクタcatのことを「Kleisli m」と呼ぶらしい
逆に、Arrow以外で使われているものってあるの?
つまり、なんでCategoryとArrowを分けた?
どういう基準で?
なぜarrはCateogryにではなく、Arrowに定義されている?
arrは一般的な関手なのだから、Categoryにあってもおかしくないような気もするが
実際に使っている例
参考
敢えて関数名とか定義とずらしているんだろうけど、逆に混乱を招く感じもするmrsekut.icon
順序だった基本