使用不同类型的Monad变压器的策略是什么?



我正在尝试实现一个简单的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 -}

这将做这两件事,并将ApplicationConfigPersistEntityBackend需求提升到顶部,用户可以捆绑提供它们。

这可能吗?

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

如果没有 - 我应该考虑哪些更改?

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

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

我能够制作一个只想要我想要的函数。秘诀是使用PostgresqlConn。

process :: ReaderT ApplicationConfig IO (Either ApplicationError ())
process = do
appConfig <- ask
connStr   <- asks connectionString
runStdoutLoggingT
$ withPostgresqlConn connStr
$ flip ($) appConfig
. runReaderT
. runExceptT
. runReaderT getResponseAndStore

你不能改用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.

最新更新