1

我正在尝试实现一个简单的 Web 服务器,它与其他一些 API 交互并在进行一些处理后存储响应。

为了封装失败的可能性(空响应、错误请求等),我使用ExceptT如下:

getExample
  :: (MonadIO m, MonadReader ApplicationConfig m)
  => ExceptT ApplicationError m [Example]
getExample = do

  partOfReq <- asks requestForSometing

  fn1 =<< fn2 partOfReq

我还有另一个函数,它使用 Persistent 中的insertMany_将响应存储在数据库中。

storeExample
  :: ( MonadIO m
     , PersistStoreWrite backend
     , PersistEntityBackend Example ~ BaseBackend backend
     )
  => [Example]
  -> ReaderT backend m ()
storeExample = insertMany_

现在我想写一个函数

getResponseAndStore = ... {- A combination of getExample and storeExample -}

这将完成这两件事,ApplicationConfig并将PersistEntityBackend需求浮出水面,用户可以在捆绑包中提供它们。

那可能吗?

如果是这样 - 策略/实施会是什么?

如果不是 - 我应该考虑哪些变化?

编辑:这就是我目前正在做的事情。

getResponseAndStore
  :: ( MonadIO m
     , MonadReader ApplicationConfig m
     , PersistStoreWrite backend
     , PersistEntityBackend Example ~ BaseBackend backend
     )
  => ReaderT backend (ExceptT ApplicationError m) ()
getResponseAndStore = storeExample =<< lift getExample
4

2 回答 2

1

我能够制作一个我想要的功能。秘诀是使用withPostgresqlConn

process :: ReaderT ApplicationConfig IO (Either ApplicationError ())
process = do

  appConfig <- ask
  connStr   <- asks connectionString

  runStdoutLoggingT
    $ withPostgresqlConn connStr
    $ flip ($) appConfig
    . runReaderT
    . runExceptT
    . runReaderT getResponseAndStore
于 2020-06-11T16:42:19.663 回答
0

你不能改用MonadError语法吗?

getExample
  :: (MonadIO m, MonadReader ApplicationConfig m, MonadError ApplicationError m)
  => [Example]
getExample = -- ...

getResponseAndStore :: (MonadIO m, MonadReader ApplicationConfig m, PersistStoreWrite backend, PersistEntityBackend Example ~ BaseBackend backend, MonadError ApplicationError m) => -- etc.
于 2020-06-11T16:05:24.320 回答