如何使ReaderT与另一个monad变压器一起工作?

时间:2014-09-26 18:09:15

标签: haskell monads monad-transformers

我想将ReaderT嵌入到另一个monad变换器中。我该怎么做呢?下面的示例使用Scotty,但我认为它与任何其他monad相同。

{-# LANGUAGE OverloadedStrings #-}

import qualified Web.Scotty
import Web.Scotty.Trans

import Data.Text.Lazy
import Control.Monad.IO.Class (liftIO)

import Control.Monad.Trans.Reader
import Control.Monad.Trans

data Config = Config Text

main :: IO ()
main = do
    let config = Config "Hello World"
    -- how to I make this line work?
    scottyT 3000 id id routes

routes :: ScottyT Text (ReaderT Config IO) ()
routes = do
    get "/" info

info :: ActionT Text (ReaderT Config IO) ()
info = do
    -- this part seems like it works!
    Config message <- lift ask
    text $ "Info: " `append` message

scottyT 3000 id id routes行上的此错误,因为scottyT需要ScottyT Text IO ()。我该如何工作?以下是当前的错误:

Server.hs: line 24, column 24:
  Couldn't match type `ReaderT Config IO' with `IO'
    Expected type: ScottyT Text IO ()
      Actual type: ScottyT Text (ReaderT Config IO) ()

1 个答案:

答案 0 :(得分:1)

您必须将您提供的参数id更改为分别具有forall a. m a -> n am Response -> IO Response类型的参数。为什么?我不知道,但我发现here的示例显示有人运行它类似于

main = do
    let config = Config "Hello, world"
        runner = flip runReaderT config
    scottyT 3000 runner runner routes

我已经测试了它,至少它可以工作。我不知道这是否是最佳实践。如果某人有更好的方法,请随意发布。