【问题标题】:How to convert an "IO (Either e a) into an ExceptT e m a如何将“IO (Either e a) 转换为ExceptionT e m a
【发布时间】:2017-07-10 08:20:06
【问题描述】:

我正在使用Control.Monad.Except 并被困在一个地方,我必须强制执行ExceptT AppError m a 操作以获得IO 操作,然后将其再次包装回ExceptT AppErr m a。如果您想知道为什么需要这样做,那是因为我需要运行的底层库函数只接受 IO 操作。在这种情况下,它将是 Database.PostgreSQL.Simple.withTransaction :: Connection -> IO a -> IO a

我如何写出以下概念的等价物:

type AppM = ExceptT AppError (ReaderT Env (LoggingT IO))

runAppM :: Env -> AppM a -> a

withTransaction :: AppM a -> AppM a
withTransaction appm = do
  conn <- getDbConnection
  env <- getEnv
  liftIO $ PGS.withTransaction conn $ runAppM appm

这是我得到的错误:

Excepted type: ExceptT AppError (ReadertT Env (LoggingT IO)) a
Actual type: ExceptT AppError (ReadertT Env (LoggingT IO)) (Either AppError a)

【问题讨论】:

  • 你问题的标题和正文是完全不同的问题。

标签: haskell monads monad-transformers


【解决方案1】:

使用构造函数ExceptT : m (Either e a) -&gt; ExceptT e m a

withTransaction :: AppM a -> AppM a
withTransaction appm = do
  conn <- getDbConnection
  env <- getEnv
  ExceptT $ PGS.withTransaction conn $ runAppM appm

【讨论】:

  • 仍然报错:Expected type: ExceptT AppError (ReaderT Env (LoggingT IO)) a // Actual type: ExceptT AppError IO a
  • 这个答案是错误的,大概是因为标题中的问题与正文中的实际问题不一样。
  • PGS.withTransaction conn $ runAppM appm 计算结果为IO (Either e a),需要将其转换为ExceptT e m a。我对这里发生的事情的理解是否存在差距?
  • 我明白了。 ExceptT $ liftIO $ PGS.withTransaction conn $ runAppM appm 是对的。 liftIOIO (Either e a) 提升到 ReaderT Env (LoggingT IO) (Either e a) 然后 ExceptT 将其提升到 AppM a
猜你喜欢
  • 1970-01-01
  • 2021-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多