Can GHC derive Functor and Applicative instances for a monad transformer?

淺唱寂寞╮ 提交于 2019-12-22 04:42:31

问题


I'm trying to implement MaybeT in the spirit of the mtl library. With this non-compiling solution:

{-# 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

...

I get the error:

Could not deduce (Applicative (MaybeT m)) arising from the superclasses of an instance declaration from the context (Monad m)

If I implement the following, it compiles:

instance (Monad m) => Applicative (MaybeT m) where
    pure = return
    (<*>) = ap 

instance (Monad m) => Functor (MaybeT m) where
    fmap = liftM

Can GHC do this for me?


回答1:


No, GHC can not currently do that. Maybe in the future it will.

The need to add applicative instances is a fairly new one, introduced with GHC 7.10 and the "burn all bridges" proposal. This fixed some warts of the previous class hierarchy, by finally requiring that monads are subclasses of applicatives which are subclasses of functors. Unfortunately, this breaks backward compatibility, and causes some inconveniences since there's no automatic way to infer the applicative instances.

Perhaps in the future GHC will allow something like

class Applicative m => Monad m where
   return :: a -> m a
   (>>=) :: m a -> (a -> m b) -> m b
   default pure = return
   default (<*>) = ap

so that one does not need to be explicit about the superclass instances. Or even something based on Template Haskell, so that a library writer can explain to GHC how to automatically derive instances (which, to some extent, is feasible right now). We shall see what comes from the GHC developers.




回答2:


GHC may well be able to derive the Functor instance, since it's fairly good at those. But the only way it knows to derive an Applicative instance is with generalized newtype deriving, which does not apply here.



来源:https://stackoverflow.com/questions/32929252/can-ghc-derive-functor-and-applicative-instances-for-a-monad-transformer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!