我正在尝试实施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
...
我收到错误:
无法推断出(Applicative (MaybeT m)) 产生于
来自上下文的实例声明的超类 (Monad 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 是 applicatives 的子类,而 applicatives 是函子的子类。不幸的是,这破坏了向后兼容性,并导致一些不便,因为没有自动方法来推断应用实例。
也许将来 GHC 会允许类似的事情
class Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
default pure = return
default (<*>) = ap
这样就不需要明确了解超类实例。或者甚至是基于 Template Haskell 的东西,以便库编写者可以向 GHC 解释如何自动派生实例(这在某种程度上现在是可行的)。我们将看看 GHC 开发者会带来什么。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)