微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

单个方法上的多个 MonadReader 约束

如何解决单个方法上的多个 MonadReader 约束

看起来没有什么可以阻止您定义这样的函数

tmp :: (MonadReader Int m,MonadReader Bool m) => m Int
tmp = ifM ask ((+1) <$> ask) ((+2) <$> ask)

所以就像一个可类型化的上下文,只要你给它一个类型,ask 就会为你提供具有该类型的环境部分,我认为这是名称阴影的合理替代。

然而,使用 MonadReader 定义的 Control.Monad.Reader认实例,看起来没有办法实际调用方法。所以我定义了一个新模块来尝试这样做:

{-# LANGUAGE FlexibleInstances,MultiParamTypeClasses,UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Control.Monad.Reader.Extra
  ( MonadReader(ask)
  ) where

import Control.Monad.Reader (MonadReader(ask,local,reader))
import Control.Monad.Trans.Class (MonadTrans(lift))

instance {-# OVERLAPPABLE #-} ( Monad m,MonadTrans t,Monad (t m),MonadReader r m
                              ) =>
                              MonadReader r (t m) where
  ask = lift ask
  local _ _ = undefined
  reader f = lift (reader f)

只要第二个实例在范围内,您就可以运行 tmp,例如 runReaderT (runReaderT tmp 1) True

不幸的是,我无法为本地找到合适的实现,因为它需要具有 local :: (r -> r) -> (t m a) -> (t m a) 类型,但似乎没有办法将 local :: (r -> r) -> m a -> m a 提升到此.

对于此实例,本地的合理实现是什么?


最小完整示例:

{-# LANGUAGE FlexibleInstances,UndecidableInstances,LambdaCase,FlexibleContexts #-}
module Tmpfundep where

import Control.Monad.Reader
  ( MonadReader(ask,reader),ReaderT(ReaderT),runReaderT
  )

instance {-# INCOHERENT #-} (Monad m,MonadReader r m) =>
                            MonadReader r (ReaderT r' m) where
  ask = ReaderT (const ask)
  local f (ReaderT m) = ReaderT (local f . m)
  reader f = ReaderT (const (reader f))

withEnv :: r -> ReaderT r m a -> m a
withEnv r m = runReaderT m r

tmp :: (MonadReader Int m,MonadReader Bool m) => m Int
tmp = ask >>= \case
  True -> (+1) <$> ask
  False -> (+2) <$> ask

main :: IO ()
main = withEnv True (withEnv (1 :: Int) tmp) >>= print

能够使用 echo main | stack exec -- runghc Tmpfundep.hs

运行它

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?