【问题标题】:Can GHC derive Functor and Applicative instances for a monad transformer?GHC 可以为 monad 转换器派生 Functor 和 Applicative 实例吗?
【发布时间】:2015-10-04 01:49:30
【问题描述】:

我正在尝试本着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

...

我得到错误:

无法推断 (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 可以为我做这件事吗?

【问题讨论】:

标签: haskell monads ghc monad-transformers


【解决方案1】:

不,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

这样就不需要明确说明超类实例。甚至是基于 Template Haskell 的东西,这样库作者就可以向 GHC 解释如何自动派生实例(在某种程度上,这在现在是可行的)。我们将看看 GHC 开发人员的成果。

【讨论】:

  • 现在,return = pure 默认是另一种方式,所以你可以忽略它。未来也有计划将return 变成pure 的同义词。
【解决方案2】:

GHC 很可能能够派生Functor 实例,因为它在这些方面相当出色。但它知道派生Applicative 实例的唯一方法是使用广义新类型派生,这在此处不适用。

【讨论】:

    猜你喜欢
    • 2019-06-30
    • 1970-01-01
    • 2011-11-05
    • 2012-01-29
    • 2015-07-02
    • 2012-11-12
    • 1970-01-01
    相关资源
    最近更新 更多