2015-10-04 50 views
7

我試圖以mtl庫的精神實現MaybeT。有了這個非編解決方案:GHC可以派生函數和應用實例的單子變壓器嗎?

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-} 

import Control.Monad 
import Control.Monad.Trans 
import Control.Monad.State 

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } 

instance (Monad m) => Monad (MaybeT m) where 
    x >>= f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f) 
    return a = MaybeT $ return (Just a) 
    fail _ = MaybeT $ return Nothing 

instance MonadTrans MaybeT where 
    lift m = MaybeT (liftM Just m) 

instance (MonadIO m) => MonadIO (MaybeT m) where 
    liftIO m = lift (liftIO m) 

instance (MonadState s m) => MonadState s (MaybeT m) where 
    get = lift get 
    put = lift . put 

... 

我得到的錯誤:

Could not deduce (Applicative (MaybeT m)) arising from the superclasses of an instance declaration from the context (Monad m)

如果我執行以下,它編譯:

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

instance (Monad m) => Functor (MaybeT m) where 
    fmap = liftM 

GHC能爲我做到這一點?

+0

相關:http://stackoverflow.com/questions/18861231/why-is-there-no-xderiveapplicative-extension – dfeuer

回答

5

不,GHC目前無法做到這一點。也許在未來它會。

需要添加應用實例是一個相當新的實例,引入GHC 7.10和「刻錄所有網橋」提案。這固定了以前類層次結構的一些瑕疵,最終要求monad是函子的子類的應用程序的子類。不幸的是,這破壞了向後兼容性,並且由於沒有自動的方式來推斷應用實例而導致一些不便。

或許未來GHC將允許類似

class Applicative m => Monad m where 
    return :: a -> m a 
    (>>=) :: m a -> (a -> m b) -> m b 
    default pure = return 
    default (<*>) = ap 

,使一個並不需要明確對超實例。甚至是基於Haskell模板的東西,這樣圖書館作者就可以向GHC解釋如何自動導出實例(這在某種程度上現在是可行的)。我們將看到什麼來自GHC開發者。

+1

現在,有一個'return = pure'默認的另一種方式,所以你可以忽略。也有計劃可能會在未來使'return'成爲'pure'的同義詞。 –

2

GHC很可能能夠推導出Functor實例,因爲它很好。但是知道派生一個Applicative實例的唯一方法是使用廣義的新類型派生,這在這裏不適用。

相關問題