【发布时间】:2014-09-26 18:09:14
【问题描述】:
我想将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) ()
【问题讨论】:
-
好吧,这可行,但我不确定它是否正确:
flip runReaderT config $ scottyT 3000 id (flip runReaderT config) routes。考虑到需要两次runReaderT,我认为这是不正确的,但我对 scotty 的了解还不够,无法知道为什么scottyT函数需要该参数 -
你能改变“转换堆栈”的顺序,即
ReaderT Config (ScottyT Text IO) ()吗? -
基于this 的回答,你可以做`scottyT 3000 (flip runReaderT) (flip runReaderT) 路线,这似乎是其他人的做法。
-
@chaosmasttter 不幸的是,没有。
get函数的类型为(ScottyError e, MonadIO m) => RoutePattern -> ActionT e m () -> ScottyT e m (),而不是更通用的(ScottyError e, MonadIO m, MonadAction a, MonadScotty s) => RoutePattern -> a e m () -> s e m () -
@chaosmasttter 我不想。我希望能够在不提升的情况下使用
Scotty的东西。
标签: haskell monads monad-transformers