【问题标题】:How do I add the Reader monad to Scotty's monad?如何将 Reader monad 添加到 Scotty 的 monad?
【发布时间】:2023-04-05 18:28:01
【问题描述】:

我正在尝试使用 Scotty 构建一个非常简单的 API。我想扩展 Scotty monad,以便我的路由处理程序操作能够访问不变的环境。我相信这样做的方法是将Reader monad 添加到堆栈中。现在我只想传递一些Text 数据。

我将 Scotty monad 扩展如下:

type BrandyScottyM = ScottyT TL.Text (ReaderT T.Text IO)
type BrandyActionM = ActionT TL.Text (ReaderT T.Text IO)

https://github.com/stu-smith/Brandy/blob/0838a63537d7e396ac82d58d460c6529349303d3/src/Core.hs

所以我的第一个问题是,这是正确的方法吗?

我已成功更改了路由处理程序的类型,但我不知道如何使用此堆栈启动 Scotty。我尝试了以下方法:

runScotty :: Port -> Text -> BrandyScottyM () -> IO ()
runScotty port file = T.scottyT port ((\f -> runReader f file)) id

https://github.com/stu-smith/Brandy/blob/0838a63537d7e396ac82d58d460c6529349303d3/src/Main.hs

但我得到了错误:

  Couldn't match type `IO' with `Data.Functor.Identity.Identity'
    Expected type: Reader Text (IO a)
      Actual type: ReaderT Text IO a
    In the first argument of `runReader', namely `f'
    In the expression: runReader f file
    In the second argument of `T.scottyT', namely
      `((\ f -> runReader f file))'
/home/stu/git/Brandy/src/Main.hs: line 36, column 65:
  Couldn't match type `ReaderT Text IO Network.Wai.Internal.Response'
                  with `IO Network.Wai.Internal.Response'
    Expected type: ReaderT Text IO Network.Wai.Internal.Response
                   -> IO Network.Wai.Internal.Response
      Actual type: ReaderT Text IO Network.Wai.Internal.Response
                   -> ReaderT Text IO Network.Wai.Internal.Response
    In the third argument of `T.scottyT', namely `id'
    In the expression: T.scottyT port ((\ f -> runReader f file)) id
    In an equation for `runScotty':
        runScotty port file = T.scottyT port ((\ f -> runReader f file)) id

所以我的第二个问题是,如何使用不同的 monad 堆栈启动 Scotty?这是我第一次尝试使用 monad 转换器,我似乎迷失了方向。

【问题讨论】:

    标签: haskell monad-transformers scotty


    【解决方案1】:

    您的方法看起来不错。类型错误是因为您应该使用runReaderT 而不是runReaderrunReader 仅适用于您使用Reader,即ReaderT,其下方只有虚拟Identity monad)。

    【讨论】:

    • 啊哈太棒了,这让我走上了正确的道路。我还必须在应用程序和操作级别创建Reader:所以最终调用是:T.scottyT port (`runReaderT` file) (`runReaderT` file)
    猜你喜欢
    • 2014-05-07
    • 2017-06-22
    • 2018-03-26
    • 2017-08-16
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 2020-08-11
    • 2021-07-18
    相关资源
    最近更新 更多