haskell - GHC 可以为 monad 转换器派生 Functor 和 Applicative 实例吗?

标签 haskell monads ghc monad-transformers

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

...

我收到错误:

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 目前无法做到这一点。也许将来会。

添加应用实例的需求是一个相当新的需求,是在 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

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

关于haskell - GHC 可以为 monad 转换器派生 Functor 和 Applicative 实例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32929252/

相关文章:

haskell - 使用/不使用 lambda 定义函数

haskell - bind 可以由 fmap 和 join 组成,那么我们必须使用一元函数 a -> m b 吗?

Haskell 的 Pairs 类型

Haskell 元组与函数参数不匹配

haskell - 'do' 表示法中的新范围

Scalaz 和主要方法

performance - 编译不安全的Haskell

string - Data.Text 的好处

haskell - IO Monad 中的链式 if/else 语句

arrays - 如何正确优化 MArray 函数以提高速度?