2014-03-30 93 views
13

我一直在使用Haxl monad(這裏描述:http://www.reddit.com/r/haskell/comments/1le4y5/the_haxl_project_at_facebook_slides_from_my_talk),它有一個有趣的特性,<*>其應用實例與Control.Monad的ap不同。這是一個關鍵特性,可以在不阻塞的情況下進行併發計算。例如,如果hfha長計算,然後MaybeT m的應用實例假定Monad m

let hf :: Haxl (a -> b) = ... 
    ha :: Haxl a = ... 
in do 
    f <- hf 
    a <- ha 
    return (f a) 

會做他們順序地,而

hf <*> ha 

將並行做它們,然後合併結果。

我希望能夠在MaybeT Haxl運行計算,但問題是,在變壓器包MaybeT m應用型實例使用一元綁定:

instance (Functor m, Monad m) => Applicative (MaybeT m) where 
    pure = return 
    (<*>) = ap 

哪裏ap = liftM2 idControl.Monad。這使得

let hmf :: MaybeT Haxl (a -> b) = ... 
    hma :: MaybeT Haxl a = ... 
in hmf <*> hma 

順序運行。這似乎是一個更好的情況下會更喜歡

instance (Applicative m) => Applicative (MaybeT m) where 
    pure = MaybeT . pure . Just 
    MaybeT f <*> MaybeT x = MaybeT $ (<*>) <$> f <*> x 

(在這裏,(<*>)在右手邊是爲Maybe單子,而對非括號的右邊是m<*>。)請注意,上下文不同 - 上述實例僅假設爲Applicative m,而變換器中的實例假定爲Functor m, Monad m

我的主要問題是實際的:我該怎麼做呢?我應該推出我自己的MaybeT monad變壓器嗎?有沒有辦法避開ghc給我的「重複實例聲明」的抱怨,如果我試着寫上面的話?

我也想知道:目前的設置是否存在變壓器封裝的設計缺陷?如果不是,爲什麼不呢?

+6

每個人都傾向於認爲超類實現完全匹配子類實現。哈克斯爾違反了這條不成文的規則,因此無法與其他人打好關係。變形金剛也假設你正在製造'Monad'變形金剛,因此它的實施。 'Applicative'「變形金剛」有更好的結構。 –

+0

@ J.Abrahamson,這不是一個規則,書面或其他。這也不是唯一的情況,其中'<*>'比'ap'更有效。在我看來'MaybeT'在這裏是錯誤的。 – dfeuer

+0

After [AMP](https://www.haskell。org/haskellwiki/Functor-Applicative-Monad_Proposal)作爲GHC 7.10的一部分廣泛傳播,我們可以重寫'Applicative(MaybeT m)'定義。目前'Applicative'不是'Monad'的超類,所以你可能會破壞大量的包。我還看到很多* Foo是Monad的實例,但不是應用程序*警告。會建議現在寫你自己的'MaybeT',或者可能做一個PR到'變形金剛'?. – phadej

回答

7

訣竅是(不像monad)應用函數是可組合的,所以你不需要(適用的)變換器,如MaybeT。相反,你可以使用Compose兩個應用性函子結合在一起:

import Control.Applicative 
import Data.Functor.Compose 

type HaxlM = Compose Haxl Maybe 

-- if you prefer to have a function for constructing values: 
haxlM :: Haxl (Maybe a) -> HaxlM a 
haxlM = Compose 

組成始終是Applicative適當的實例,並只使用其組件的Applicative實例。例如:

test = getZipList . getCompose 
     $ (+) <$> Compose (ZipList [Just 1, Nothing, Just 3]) 
      <*> Compose (ZipList [Nothing, Just 20, Just 30]) 

[Nothing,Nothing,Just 33]產生。

+1

好的,很酷。但在這種情況下,我不能使用monad操作,對吧? (一般Haxl計算使用應用程序和monad來表示不同的數據流。)有什麼方法可以獲得兩全其美的好處(即,一個HaxlM monad,ap!= <*>,而不需要從頭開始編寫)? – davidsd

+1

@davidsd我猜不。你也許可以使用'FlexibleInstances' /'FlexibleContexts'爲'Compose Haxl Maybe'創建monad實例,但是最好從零開始創建'HaxlM' monad。 –

+2

只要我們走上這條道路,值得注意的是'Applicative'產品也是'Applicative'。只要有一個自然轉變可以讓偏見工作,那麼與「Applicative」總和相同:http://comonad.com/reader/2012/abstracting-with-applicatives/ –

相關問題