在ScottyT中使用ReaderT转换器(vs ActionT) [英] Using ReaderT transformer in ScottyT (vs ActionT)

查看:155
本文介绍了在ScottyT中使用ReaderT转换器(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆