2016-11-21 109 views
6

下面是我們如何定義KleisliFunctor與KleisliFunctor類似的東西是什麼?

class (Monad m, Functor f) => KleisliFunctor m f where 
    kmap :: (a -> m b) -> f a -> f b 
    kmap f = kjoin . fmap f 

    kjoin :: f (m a) -> f a 
    kjoin = kmap id 

請問這類型的類

class (Functor f, Monad m) => Absorb f m where 
    (>>~) :: f a -> (a -> m b) -> m b 
    a >>~ f = ajoin $ fmap f a 

    ajoin :: f (m a) -> m a 
    ajoin a = a >>~ id 

配合地方分成類別理論?什麼是法律?他們是

a >>~ g . f  === fmap f a >>~ g 
a >>~ (f >=> g) === a >>~ f >>= g 

+0

您是否有一些特殊的示例類型允許使用'Absorb'實例,但沒有足夠強大的標準實例來實現'(>>〜)'和'ajoin'? – leftaroundabout

+0

@leftaroundabout,我需要'Absorb'來實現一般化的monadic摺疊,它允許在'f'函數中保留一個累加器,但將結果返回到'm'單子。見例如[本](https://github.com/effectfully/prefolds/blob/374257b12f9a2af752862addafe456cded9c0efb/test/Main.hs#L297)。 – user3237465

回答

4

這是一個推測性的答案。謹慎行事。

我們先考慮KleisliFunctor,注重綁定樣箭頭映射:

class (Monad m, Functor f) => KleisliFunctor m f where 
    kmap :: (a -> m b) -> f a -> f b 

對於這實際上是從m的Kleisli類別函子來Haskkmap一直遵守相關的函子法則:

-- Mapping the identity gives identity (in the other category). 
kmap return = id 
-- Mapping a composed arrow gives a composed arrow (in the other category). 
kmap (g <=< f) = kmap g . kmap f 

事實上,有兩個Functor s涉及使事情有點不尋常,b這並非不合理 - 例如,法律確實適用於mapMaybe,這是KleisliFunctor後暗示的第一個具體示例。

至於Absorb,我會翻轉綁定樣方法清楚起見:

class (Functor f, Monad m) => Absorb f m where 
    (~<<) :: (a -> m b) -> f a -> m b 

如果我們要尋找到KleisliFunctor東西類似,立即出現一個問題是哪些類別將有功能類型爲f a -> m b,如箭頭所示。它肯定不能是哈斯克,因爲它的身份(類型f a -> m a)不能是id。我們不僅要弄清楚身份,而且要弄清楚組成。對於一些不完全不同於Monad ...

idAbsorb :: f a -> m a 
compAbsorb :: (f b -> m c) -> (f a -> m b) -> (f a -> m c) 

...我能想到的,現在唯一可行的是有一個單子射爲idAbsorb,而在相反方向上使用第二單子射(即是從mf),因此compAbsorb可以通過應用第一個函數,然後返回到f並最終應用第二個函數來實現。我們需要解決這個問題,以便了解我的假設是否合適,如果這種方法有效,以及它是否會爲您的目的提供有用的信息。

+0

「哪個類別的函數的類型爲'fa - > mb'爲箭頭」 - 我不知道箭頭,但是這些對象不在'Hask'上的兩個endofunctor的逗號類中:'f'和' M'?不知道它給了我們什麼。'compAbsorb'對我來說非常不滿意,因爲我不希望'fb - > mc'成爲單態射線,因爲我的'f'有一個相當虛擬的monad實例,我的用例是兩個,在這個問題下)並不需要從'm'到'f',我不想強​​加這一點。感謝你的回答,它已經澄清了一些事情給我。 – user3237465

+1

@ user3237465看着你的代碼似乎證實了你的期望。特別是試圖通過嘗試'idAbsorb = slift'和'compAbsorb = g來做「明顯的」事情。 runDriveT。 f'落在第一個障礙 - compAbsorb idAbsorb f'不是'f'(它將'Stop'變成'More'),所以我們甚至沒有一個類別。從'DriveT m'到'm'會產生麻煩,正如你所說的,在你的用例的組合過程中做這件事很沒有意義。順便說一句,請注意你的'(>〜>)'既不是'(> =>)'也不是'flip compAbsorb',這似乎證實你確實需要別的東西。 – duplode