我有类型
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
,但我不知道这是如何适用的。
我们非常感谢您对实例类型的任何帮助,我希望自己实现ask
和local
,因为主要目标是学习。
感谢。
我使用了FlexibleInstances, MultiParamTypeClasses, UndecidableInstances
和
instance (ScottyError e, Monad m, MonadReader r m) => MonadReader r (ActionT e m) where
ask = lift ask
仍在努力实施本地化。我还假设UndecidableInstances
不好?
我认为我真正需要的是。
instance (ScottyError e, Monad m, MonadReader r m) => MonadReader r (ActionT e (ReaderT r m)) where
但我仍然无法弄明白local
答案 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。
欢迎任何有关实施的意见。