2012-12-18 52 views
33

在分類理論中,monad可以由兩個伴隨函數構成。特別是,如果Çd是類別和FⅧ:C - > dG:d - 「ç是伴隨函子,在這個意義上,有一個雙射對應於Haskell中常見monads的伴隨函子對是什麼?

坎(FX,Y)=坎(X,GY)

每個Xçÿ in D then the composition G o F:C - > C是一個monad。


一種這樣的一對伴隨函子可以通過固定型b並採取FG給予是

data F b a = F (a,b) 
data G b a = G (b -> a) 

instance Functor (F b) where 
    fmap f (F (a,b)) = F (f a, b) 

instance Functor (G b) where 
    fmap f (G g) = G (f . g) 

和HOM-集之間的雙射由討好給出(模構造函數) :

在這種情況下
iso1 :: (F b a -> c) -> a -> G b c 
iso1 f = \a -> G $ \b -> f (F (a,b)) 

iso2 :: (a -> G b c) -> F b a -> c 
iso2 g = \(F (a,b)) -> let (G g') = g a in g' b 

相應單子是

data M b a = M { unM :: b -> (a,b) } 

instance Monad (M b) where 
    return a = M (\b -> (a,b)) 
    (M f) >>= g = M (\r -> let (a,r') = f r in unM (g r') a) 

我不知道這個單子的名稱應該是什麼,但它似乎像一個讀者單子,圍繞一塊過寫信息(編輯載: dbaupp中指出,評論說,這是State單子。)

所以State單子可以「分解」爲一對伴隨函子FG的,我們可以寫

State = G . F 

到目前爲止,一切都很好。


現在,我試圖找出如何分解等常見單子到對伴隨函子 - 例如Maybe[]ReaderWriterCont - 但我不能找出對什麼伴隨函數,我們可以將它們「分解」成它們。

唯一簡單的情況似乎是Identity單子,它可以被分解爲任意一對函子F的和G使得F是逆G(在尤其,可以只取F = IdentityG = Identity)。

任何人都可以點亮一下嗎?

+4

您構建的monad是狀態monad。 – huon

+6

啊,當然。我將把它添加到「我已經徹底改變了一個衆所周知的monad實例但沒有意識到它的時代」的列表中。 –

+3

將monad分解成指定函數的組合並不是唯一的,事實上,對於任何monad,都有一個這樣的分解類型。可能兩種最有用的分解方法是終端和初始方法:右邊伴侶是健忘函數的那些分解方法,它們來自(1)單子的代數範疇(Eilenberg-Moore範疇)和(2)自由代數範疇對於monad(Kleisli類)。 –

回答

15

您要找的是Kleisli category。它最初是爲了表明每個monad可以由兩個伴隨函數構造而成。

問題是,Haskell Functor不是一個泛型函數,它是Haskell類別中的內函數。因此,我們需要不同的東西(據我所知)其它類之間代表函子:

{-# LANGUAGE FunctionalDependencies, KindSignatures #-} 
import Control.Arrow 
import Control.Category hiding ((.)) 
import qualified Control.Category as C 
import Control.Monad 

class (Category c, Category d) => CFunctor f c d | f -> c d where 
    cfmap :: c a b -> d (f a) (f b) 

注意,如果我們採取->兩個cd我們得到的哈斯克爾類別的內切仿函數,它是剛剛類型fmap

cfmap :: (a -> b) -> (f a -> f b) 

現在我們有一個代表兩個給定類別cd,我們可以表達對一個給定的單子兩個伴隨函子之間的函子顯式類型類。左邊的一個映射對象a只是a和映射態射f(return .) f

-- m is phantom, hence the explicit kind is required 
newtype LeftAdj (m :: * -> *) a = LeftAdj { unLeftAdj :: a } 
instance Monad m => CFunctor (LeftAdj m) (->) (Kleisli m) where 
    cfmap f = Kleisli $ liftM LeftAdj . return . f . unLeftAdj 
    -- we could also express it as liftM LeftAdj . (return .) f . unLeftAdj 

右一個映射對象a反對m a和同態映射gjoin . liftM g,或等同於(=<<) g

newtype RightAdj m a = RightAdj { unRightAdj :: m a } 
instance Monad m => CFunctor (RightAdj m) (Kleisli m) (->) where 
    cfmap (Kleisli g) = RightAdj . join . liftM g . unRightAdj 
    -- this can be shortened as RightAdj . (=<<) g . unRightAdj 

(如果有人知道如何在Haskell中表達這個更好的方法,請告訴我。)

13
  • Maybe來自自由仿成尖套類別和健忘函子回
  • []來自自由仿成類羣的分類和健忘函子回

但這些都不類別是Hask的子類別。

+0

謝謝湯姆。我已經設法通過這兩個細節 - 現在弄清楚其他例子的相應函數是什麼。 –

+2

而「連接r」來自逆變函數* Opr:Hask^op - > Hask *與其自身的連接,其中* Op r a = a - > r *。 –

+0

很確定這些都是Eilenberg-Moore的附屬品,因爲它的價值。 –

7

正如你所觀察到的,每對伴隨函數都會產生一個monad。反之亦然:每一個monad都以這種方式出現。事實上,它是以兩種規範的方式進行的。一個是Petr描述的Kleisli建築;另一個是Eilenberg-Moore建築。事實上,Kleisli是最初的這種方式,而E-M是終端之一,在一對合適的函子的適當類別中。他們在1965年被獨立發現。如果你想了解細節,我強烈推薦Catsters videos

+0

謝謝傑里米 - 有幾個人向我推薦貓貓,我真的應該檢查一下。 –

+0

什麼是F - |國家單元格的愛倫貝格 - 摩爾聯合的G? – Romuald

相關問題