定義「Monads只是在endofunctors類別monoid。」,雖然真的是一個壞的地方開始。這是來自blog post,很大程度上是爲了開玩笑。但是如果你對通信感興趣,可以在Haskell中演示:
類別的外行描述是對象之間對象和態射的抽象集合。類別之間的映射被稱爲函子並將對象映射到對象和態射以相關聯並保留身份。一個endofunctor是從一個類別本身的函數。滿足所謂naturality conditions函子之間
{-# LANGUAGE MultiParamTypeClasses,
ConstraintKinds,
FlexibleInstances,
FlexibleContexts #-}
class Category c where
id :: c x x
(.) :: c y z -> c x y -> c x z
class (Category c, Category d) => Functor c d t where
fmap :: c a b -> d (t a) (t b)
type Endofunctor c f = Functor c c f
映射被稱爲自然變換。在Haskell中,這些是類型爲(Functor f, Functor g) => forall a. f a -> g a
的多態函數。
一個類別C
一個單子是三件事(T,η,μ)
,T
是endofunctor和1
是C
身份仿函數。畝和ETA是滿足一個triangle identity和關聯身份兩個自然的變換,並且被定義爲:
在Haskell μ
是join
和η
是return
return :: Monad m => a -> m a
join :: Monad m => m (m a) -> m a
單子的Haskell中分類定義可以寫成:
class (Endofunctor c t) => Monad c t where
eta :: c a (t a)
mu :: c (t (t a)) (t a)
綁定操作者可以從這些中導出。
(>>=) :: (Monad c t) => c a (t b) -> c (t a) (t b)
(>>=) f = mu . fmap f
這是一個完整的定義,但等效您也可以顯示單子法律可以表示爲含半幺羣的法律與函子範疇。我們可以構造這個函數類別,它是一個以對象作爲函子(即類別之間的映射)和自然變換(即函數之間的映射)作爲態射的類別。在一個endofunctor類中,所有函數都是同一類的函數。
newtype CatFunctor c t a b = CatFunctor (c (t a) (t b))
我們可以證明這引起了一類與函子組成態射組成:
-- Note needs UndecidableInstances to typecheck
instance (Endofunctor c t) => Category (CatFunctor c t) where
id = CatFunctor id
(CatFunctor g) . (CatFunctor f) = CatFunctor (g . f)
的幺具有通常的定義:
class Monoid m where
unit :: m
mult :: m -> m -> m
過的A類幺函子具有自然轉換作爲身份a和乘法運算相結合的自然轉換。可以定義Kleisli組合來滿足乘法律。
(<=<) :: (Monad c t) => c y (t z) -> c x (t y) -> c x (t z)
f <=< g = mu . fmap f . g
所以你有它「單子只是幺在endofunctors的範疇」,這是從endofunctors和(畝,ETA)單子的普通清晰度的只是一個「pointfree」版本。
instance (Monad c t) => Monoid (c a (t a)) where
unit = eta
mult = (<=<)
隨着位替換的一個可以證明的(<=<)
的monoidal屬性是單子的自然變換的三角形和關聯圖的等效聲明。
f <=< unit == f
unit <=< f == f
f <=< (g <=< h) == (f <=< g) <=< h
如果你有興趣diagrammatic representations我已經寫了一些關於用繩子圖代表他們。
啊,Monad是endfuctor,我怎麼錯過了。現在很清楚,謝謝。 –