如何编写在RIO环境中执行任意MonadUnliftIO的方括号函数?

在以下情况下,我可以在initCass' fdsEnv MonadUnliftIO m块中直接使用RIO(类型为do):

initCass :: RIO FdsEnv ClientState
initCass = do
  fdsEnv <- ask
  initCass' fdsEnv

initCass' :: MonadUnliftIO m => FdsEnv -> m ClientState
initCass' fdsEnv = do
  let config = fdsConfig fdsEnv
  let logger = fdsLogger fdsEnv
  initCassandra (dbName config) (dbHost config) (dbPort config) logger

但是,当我尝试在此处执行类似操作时:

runClientSafe :: MonadUnliftIO m => (ClientState -> m a) -> RIO FdsEnv a
runClientSafe cliFun = do
  fdsEnv <- ask
  bracket (runRIO fdsEnv initCass) shutdown cliFun

我得到一个错误:

    • Couldn't match type ‘m’ with ‘RIO FdsEnv’
      ‘m’ is a rigid type variable bound by
        the type signature for:
          runClientSafe :: forall (m :: * -> *) a.
                           MonadUnliftIO m =>
                           (ClientState -> m a) -> RIO FdsEnv a
        at src/FDS/Database/Cassandra.hs:75:1-72
      Expected type: RIO FdsEnv a
        actual type: m a
    • In a stmt of a 'do' block:
        bracket (runRIO fdsEnv initCass) shutdown cliFun
      In the expression:
        do fdsEnv <- ask
           bracket (runRIO fdsEnv initCass) shutdown cliFun
      In an equation for ‘runClientSafe’:
          runClientSafe cliFun
            = do fdsEnv <- ask
                 bracket (runRIO fdsEnv initCass) shutdown cliFun
    • Relevant bindings include
        cliFun :: ClientState -> m a
          (bound at src/FDS/Database/Cassandra.hs:76:15)
        runClientSafe :: (ClientState -> m a) -> RIO FdsEnv a
          (bound at src/FDS/Database/Cassandra.hs:76:1)
   |
78 |   bracket (runRIO fdsEnv initCass) shutdown cliFun
   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我认为差异在于,在第一种情况下,initCass'的m解析为RIO FdsEnv,所以这是有道理的。我想真正需要的是一种从MonadUnliftIO m -> RIO e开始的方法,但不确定是否可行。

feixuezhangluo 回答:如何编写在RIO环境中执行任意MonadUnliftIO的方括号函数?

为@K。 A. Buhr建议,通常情况下,您将留在同一个monad中,以便使用RIO:

runClientSafe :: (ClientState -> RIO FdsEnv a) -> RIO FdsEnv a
runClientSafe cliFun = bracket initCass shutdown cliFun

话虽如此,在另一种情况下,您希望函数是多态的,但仍与RIO统一,就像您在问题中说的那样:

  

我想真正需要的是一种从MonadUnliftIO m -> RIO e开始的方法

您可以使用RankNTypes解决此问题:

runClientSafe :: (forall m. MonadUnliftIO m => ClientState -> m a) -> RIO FdsEnv a
runClientSafe cliFun = bracket initCass shutdown cliFun
本文链接:https://www.f2er.com/3156955.html

大家都在问