GHC可以为monad变压器派生Functor和Applicative实例吗?
我试图以mtl
库的精神实现MaybeT
。 有了这个非编译解决方案:
{-# 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
...
我收到错误:
由于上下文中的实例声明的超类(Monad m)导致无法推论(Applicative(MaybeT m)),
如果我执行以下内容,它会编译:
instance (Monad m) => Applicative (MaybeT m) where
pure = return
(<*>) = ap
instance (Monad m) => Functor (MaybeT m) where
fmap = liftM
GHC能为我做这个吗?
不,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开发者。
GHC很可能能够派生出Functor
实例,因为它很好。 但是它知道派生一个Applicative
实例的唯一方法是使用广义的新类型派生,这在这里不适用。
上一篇: Can GHC derive Functor and Applicative instances for a monad transformer?