在ScottyT中使用ReaderT转换器(vs ActionT) [英] Using ReaderT transformer in ScottyT (vs ActionT)
问题描述
我试图使用ReaderT monad变压器方法通过基于Scotty的应用程序进行线程配置,并且遇到麻烦。在定义路由时(因为它们中的一些取决于配置)以及处理实际请求时,我必须使用配置。
后者在ActionT中工作得很好,但无论我尝试什么,我都无法在ScottyT中获得正确的类型。
以下是我从Scotty GitHub存储库的ReaderT样本编译的最小示例:
{ - #LANGUAGE GeneralizedNewtypeDivingiving# - }
{ - #LANGUAGE OverloadedStrings# - }
module主要在哪里
导入Control.Applicative
导入Control.Monad.Reader(MonadIO,MonadReader,ReaderT,请求,提升,runReaderT)
导入Data.Default.Class(def)
import Data.Text.Lazy(Text,pack)
import Prelude
import Web.Scotty.Trans(ScottyT,get,scottyOptsT,text,capture)
数据Config = Config
{environment :: String
}派生(Eq,Read,Show)
newtype ConfigM a = ConfigM
{runConfigM :: ReaderT Config IO a
} d eriving(Applicative,Functor,Monad,MonadIO,MonadReader Config)
application :: ScottyT Text ConfigM()
application = do
get/$ do
e < - lift $请求环境
文本$ pack $ show e
路径< - lift $请求环境
get(捕获路径)$ do
text $ pack $Hello,custom path
$ b $ main :: IO()
main = scottyOptsT def runIO application其中
runIO :: ConfigM a - > IO a
runIO m = runReaderT(runConfigM m)config
config :: Config
config = Config
{environment =Development
}
我得到的错误是:
•没有使用'lift'产生的(Control.Monad.Trans.Class.MonadTrans
(ScottyT Text))
的实例
•在do块的路径中:path< - lift $ asks environment
我已经通过代码描述了ScottyT类型的代码,实际上似乎没有为它定义的MonadTrans实例。然而,我并不觉得自己有足够的法力和Haskell经验来找到解决办法,并希望得到任何帮助!
b
谢谢!
有了集体意识,我们都能找到目前可行的解决方案问题。
ScottyT类型是一个monad变换器,其后是 https://github.com/scotty-web/scotty/pull/167 被合并,因此目前没有办法以这种方式使用它。有一个公关 https://github.com/scotty-web/scotty/pull/ 181 旨在将这个特性带回来,但据我所知,它从来没有合并过。
因为它不是一个monad变压器,所以我们只能包装它
{ - #LANGUAGE GeneralizedNewtypeDeriving# - }
{ - #LANGUAGE OverloadedStrings# - }
模块Main其中
导入Control.Applicative
导入Control.Monad.Reader(MonadIO,MonadReader,ReaderT,请求,提升,runReaderT)
import Data.Default .class(def)
import Data.Text.Lazy(Text,pack)
import Prelude
import Web.Scotty.Trans(ScottyT,get,scottyOptsT,text,capture)
data Config = Config
{environment :: String
}派生(Eq,Read,Show)
newtype ConfigM a = ConfigM
{runConfigM :: ReaderT配置IO a
}派生(Applicative,Functor,Monad,MonadIO,MonadRead er配置)
application :: ConfigM(ScottyT Text ConfigM())
application = do
path< - 询问环境
返回$
get/$ do
e< - lift $请求环境
文本$ pack $ show e
get(捕获路径)$
text $ pack $Hello,custom path
runIO :: Config - >配置a - > IO a
runIO cm = runReaderT(runConfigM m)c
main :: IO()
main = do
let config = Config {environment =/ path }
app < - runIO config application
scottyOptsT def(runIO config)app
感谢大家帮助我,希望这可以帮助像我这样的另一个流浪Scotty:)。
I'm trying to thread configuration through my Scotty based application using ReaderT monad transformer approach, and having trouble doing so. I have to use configuration both when defining routes (as some of them depend on the config) and when handling actual requests.
The latter works just fine in the ActionT, but no matter what I try I just can't get the types right in ScottyT.
Here's the minimal example I compiled from the ReaderT sample from Scotty GitHub repository:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Applicative
import Control.Monad.Reader (MonadIO, MonadReader, ReaderT, asks, lift, runReaderT)
import Data.Default.Class (def)
import Data.Text.Lazy (Text, pack)
import Prelude
import Web.Scotty.Trans (ScottyT, get, scottyOptsT, text, capture)
data Config = Config
{ environment :: String
} deriving (Eq, Read, Show)
newtype ConfigM a = ConfigM
{ runConfigM :: ReaderT Config IO a
} deriving (Applicative, Functor, Monad, MonadIO, MonadReader Config)
application :: ScottyT Text ConfigM ()
application = do
get "/" $ do
e <- lift $ asks environment
text $ pack $ show e
path <- lift $ asks environment
get (capture path) $ do
text $ pack $ "Hello, custom path"
main :: IO ()
main = scottyOptsT def runIO application where
runIO :: ConfigM a -> IO a
runIO m = runReaderT (runConfigM m) config
config :: Config
config = Config
{ environment = "Development"
}
The error I'm getting is:
• No instance for (Control.Monad.Trans.Class.MonadTrans
(ScottyT Text))
arising from a use of ‘lift’
• In a stmt of a 'do' block: path <- lift $ asks environment
I've looked through the code where ScottyT type is outlined, and indeed there doesn't seem to be an instance of MonadTrans defined for it.
However, I don't feel I have enough both mana and Haskell experience to find a way out of it and would appreciate any help!
Thank you!
With a collective mind we all came to a currently viable solution to the problem.
ScottyT type cased to be a monad transformer with after https://github.com/scotty-web/scotty/pull/167 got merged, therefore there's currently no way of using it this way. There was a PR https://github.com/scotty-web/scotty/pull/181 aimed at bringing that feature back, but as far as I understood it has never got merged.
Since it's not a monad transformer we can only wrap it again:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Applicative
import Control.Monad.Reader (MonadIO, MonadReader, ReaderT, asks, lift, runReaderT)
import Data.Default.Class (def)
import Data.Text.Lazy (Text, pack)
import Prelude
import Web.Scotty.Trans (ScottyT, get, scottyOptsT, text, capture)
data Config = Config
{ environment :: String
} deriving (Eq, Read, Show)
newtype ConfigM a = ConfigM
{ runConfigM :: ReaderT Config IO a
} deriving (Applicative, Functor, Monad, MonadIO, MonadReader Config)
application :: ConfigM (ScottyT Text ConfigM ())
application = do
path <- asks environment
return $
get "/" $ do
e <- lift $ asks environment
text $ pack $ show e
get (capture path) $
text $ pack $ "Hello, custom path"
runIO :: Config -> ConfigM a -> IO a
runIO c m = runReaderT (runConfigM m) c
main :: IO ()
main = do
let config = Config { environment = "/path" }
app <- runIO config application
scottyOptsT def (runIO config) app
Thanks everyone for helping me out, and hopefully this helps another wandering Scotty like me :).
这篇关于在ScottyT中使用ReaderT转换器(vs ActionT)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!