3

我有类型

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

4

2 回答 2

1

正如您自己回答的那样,您需要UndecidableInstances实现完全通用的MonadReader实例。这是一个必要的邪恶,您可以在所有实现此类通用 monad 类型类实例的库中看到它。

恐怕实施local起来会有问题。如果您查看标准实例,它们都使用某种特定于特定 monad 的映射函数。而且由于似乎既没有ActiveT导出这种方法或其内部结构,它看起来也不可行。

于 2014-04-18T15:06:22.483 回答
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。

欢迎对实施提出任何意见。

于 2014-04-19T05:54:27.997 回答