Scotty的ActionT的MonadReader实例

时间:2014-04-18 05:21:44

标签: haskell scotty

我有类型

ActionT TL.Text (ReaderT T.Text IO)

我试图为此制作一个MonadReader实例,这样我就不必解除问题,但总是得到

 (All instance types must be of the form (T a1 ... an)
  where a1 ... an are *distinct type variables*,
  and each type variable appears at most once in the instance head.
  Use -XFlexibleInstances if you want to disable this)

我尝试了一堆实例类型,下面是一对,但是他们总是遇到上述错误

instance MonadReader T.Text (ActionT TL.Text (ReaderT T.Text IO))    

instance MonadReader r (ActionT TL.Text (ReaderT r IO))

instance (ScottyError e, MonadReader r m) => MonadReader r (ActionT e (ReaderT r m))

我觉得我错过了一些基本的实例。我想我理解FlexibleInstances,但我不知道这是如何适用的。

我们非常感谢您对实例类型的任何帮助,我希望自己实现asklocal,因为主要目标是学习。

感谢。

更新

我使用了FlexibleInstances, MultiParamTypeClasses, UndecidableInstances

instance  (ScottyError e, Monad m, MonadReader r m) => MonadReader r (ActionT e m) where
  ask = lift ask

仍在努力实施本地化。我还假设UndecidableInstances不好?

更新2

我认为我真正需要的是。

instance  (ScottyError e, Monad m, MonadReader r m) => MonadReader r (ActionT e (ReaderT r m)) where

但我仍然无法弄明白local

2 个答案:

答案 0 :(得分:1)

在您自己回答时,您需要UndecidableInstances来实现完全通用的MonadReader实例。这是一个必要的恶,你可以在所有实现这种通用monad类型类实例的库中看到它。

我担心实施local会成为一个问题。如果查看the standard instances,它们都会使用某种特定于monad的映射函数。而且由于似乎ActiveT都不会导出这样的方法或其内部,因此它看起来并不可行。

答案 1 :(得分:1)

实例将是

instance  (ScottyError e, Monad m, MonadReader r m) => MonadReader r (ActionT e (ReaderT r m)) where

然而,Scotty没有公开实现本地所需的功能。

我正在尝试编写一个mapActionT来实现local,如果我找出要执行该操作的类型,我会更新此答案:)

编辑:

我想我有mapActionT,但我不确定。

mapActionT :: (Monad m, Functor n, ScottyError e) => (forall a . m a -> n a) -> ActionT e m b -> ActionT e n b
mapActionT nat m = ActionT $ flip mapErrorT (runAM m) $ \rt -> 
        flip mapReaderT rt $ \st ->
            StateT $ \s -> fmap (\a -> (a,s)) (nat (evalStateT st s))

我最终从卷扬机复制了类型签名,这样我就可以为我的fmap引入Functor n。

欢迎任何有关实施的意见。