GHC 可以为 monad 转换器派生 Functor 和 Applicative 实例吗?
Can GHC derive Functor and Applicative instances for a monad transformer?
我正在努力实现 MaybeT
本着 mtl
库的精神。使用此非编译解决方案:
{-# 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 可以帮我做这个吗?
GHC 很可能能够导出 Functor
实例,因为它在这些方面相当出色。但是它知道派生 Applicative
实例的唯一方法是使用广义的新类型派生,这在这里不适用。
不,GHC 目前无法做到这一点。也许以后会。
添加应用实例的需求是一个相当新的需求,在 GHC 7.10 和 "burn all bridges" 提案中引入。这修复了之前 class 层次结构的一些缺陷,最终要求 monad 是应用程序的子class,而应用是函子的子class。不幸的是,这会破坏向后兼容性,并造成一些不便,因为没有自动推断适用实例的方法。
也许将来 GHC 会允许像
这样的东西
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
default pure = return
default (<*>) = ap
这样就不需要明确说明 superclass 实例。或者甚至是基于模板 Haskell 的东西,这样库编写者就可以向 GHC 解释如何自动派生实例(在某种程度上,现在是可行的)。我们将看到来自 GHC 开发人员的内容。
我正在努力实现 MaybeT
本着 mtl
库的精神。使用此非编译解决方案:
{-# 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 可以帮我做这个吗?
GHC 很可能能够导出 Functor
实例,因为它在这些方面相当出色。但是它知道派生 Applicative
实例的唯一方法是使用广义的新类型派生,这在这里不适用。
不,GHC 目前无法做到这一点。也许以后会。
添加应用实例的需求是一个相当新的需求,在 GHC 7.10 和 "burn all bridges" 提案中引入。这修复了之前 class 层次结构的一些缺陷,最终要求 monad 是应用程序的子class,而应用是函子的子class。不幸的是,这会破坏向后兼容性,并造成一些不便,因为没有自动推断适用实例的方法。
也许将来 GHC 会允许像
这样的东西class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
default pure = return
default (<*>) = ap
这样就不需要明确说明 superclass 实例。或者甚至是基于模板 Haskell 的东西,这样库编写者就可以向 GHC 解释如何自动派生实例(在某种程度上,现在是可行的)。我们将看到来自 GHC 开发人员的内容。