本文介绍了Scotty:连接池作为monad reader的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 有数万亿的monad教程,包括读者,当你阅读它时,似乎很清楚。但是,当你真的需要写作的时候,它就变成了另外一回事。 我从来没有使用Reader,只是在实践中从未接触过。所以我不知道如何去做,但我读了它。 我需要在Scotty中实现一个简单的数据库连接池,以便每个操作都可以使用池。该池必须是全局的,并且可以通过所有操作功能进行访问。我读到了读取monad的方法。如果还有其他方法,请告诉我。 您能帮我解释一下如何正确使用Reader吗? 如果我看到自己的例子是如何完成的,我可能会学得更快。 { - #LANGUAGE OverloadedStrings# - } 模块DB其中 导入Data.Pool 导入Database.MongoDB - 从配置 ip =127.0.0.1 db =index - 创建连接池 pool :: IO(Pool Pipe) pool = createPool(runIOE $ connect $ host ip)close 1 300 5 - 使用连接池运行数据库操作 run :: Action IO a - > IO(或者失败a)执行act = flip withResource(\ x - > access x master db act)=<<游泳池 所以上面很简单。我想在每个Scotty操作中使用'run'函数来访问数据库连接池。现在,问题是如何将它包装在Reader monad中以使其可以被所有函数访问?我明白,'pool'变量必须与所有Scotty动作函数一样'全球'。 谢谢。 UPDATE 我正在用完整的代码片段更新问题。我在哪里通过函数链中的'pool'变量。如果有人可以展示如何改变它来利用monad Reader。 我不明白该怎么做。 { - #LANGUAGE OverloadedStrings# - } 模块Main其中 导入Network.HTTP.Types 导入Web.Scotty 将合格的Data.Text导入为T 导入合格的Data.Text。 Lazy as LT import Data.Text.Lazy.Internal import Data.Monoid(mconcat) import Data.Aeson(object,(。=),encode) import Network .Wai.Middleware.Static 导入Data.Pool 导入Database.MongoDB 导入Control.Monad.Trans(升降机,升降机) main = do - 创建可供所有操作函数访问的连接池 pool< - createPool(runIOE $ connect $ host127.0.0.1)close 1 300 5 scotty 3000(basal pool) basal :: Pool Pipe - > ScottyM() basal pool = do middleware $ staticPolicy(noDots> - > addBasestatic) get/ json(showJson pool) showJson :: Pool Pipe - > ActionM() showJson pool = do let run = withResource pool(\pipe-> access pipe masterindexact)d< - lift $ run $ fetch(select []tables) let r = either(const [])id d text $ LT.pack $ show r 谢谢。 更新2 我试图按照下面的建议方式去做,但它不起作用。 如果有人有任何想法,请。编译错误的列表太长了,我甚至不知道从哪里开始.... main = do pool< - createPool(runIOE $ connect $ host127.0.0.1)close 1 300 5 scotty 3000 $ runReaderT basal pool basal :: ScottyT LT.Text( ReaderT(Pool Pipe)IO)() basal = do 中间件$ staticPolicy(noDots> - > addBasestatic) get/ json$ showJson showJson :: ActionT LT.Text(ReaderT(Pool Pipe)IO)() showJson = do p< - lift ask let rdb a = withResource p(\管道 - >访问管道主索引a)j< - liftIO $ rdb $ fetch(选择[]表)文本$ LT.pack $ show j UPDATE 3 em> cdk 这个问题也有帮助:如何添加Reader monad到Scotty的monad 这是编译的版本。 导入限定的Data.Text.Lazy为T 导入限定的数据.Text.Lazy.Encoding as T import Data.Text.Lazy(Text) import Control.Monad.Reader import Web.Scotty.Trans import Data.Pool import Database.MongoDB $ b类型ScottyD = ScottyT文本(ReaderT(Pool Pipe)IO)类型ActionD = ActionT Text(ReaderT(Pool Pipe)IO) - 从配置中获取数据 ip =127.0.0.1 db =basal main = do pool< - createPool( runIOE $ connect $ host ip)close 1 300 5 let read = \r - > runReaderT r pool scottyT 3000 read read basal $ b $ - 应用程序,meaddleware和路由 basal :: ScottyD() basal = do get /拍摄 - 路线动作处理程序 shoot :: ActionD()拍摄=做r html $ T.pack $ show r - 数据库访问快捷方式 rundb :: Action IO a - > ActionD(或者失败a) rundb a = do pool< - lift ask liftIO $ withResource pool(\ pipe-> access pipe master db a) 解决方案我一直在努力弄清楚这个确切的问题。感谢关于这个SO问题的提示,以及其他研究,我提出了以下适用于我的方法。你缺少的关键是使用 scottyT 毫无疑问,编写runDB有一种更漂亮的方式,但是我在Haskell中没有太多经验,所以如果你可以做得更好,请发布它。 type MCScottyM = ScottyT TL.Text (ReaderT(Pool Pipe)IO) type MCActionM = ActionT TL.Text(ReaderT(Pool Pipe)IO) $ b $ main :: IO() main = do pool< - createPool(runIOE $ connect $ host127.0.0.1)close 1 300 5 scottyT 3000(f pool)(f pool)$ app where f = \\ \\ p - > \r - > runReaderT rp app :: MCScottyM() app = do middleware $ staticPolicy(noDots> - > addBasepublic) get/ $ do p< - runDB dataSources html $ TL.pack $ show p runDB :: Action IO a - > MCActionM(或者失败a) runDB a =(lift ask)>> =(\ p - > liftIO $ withResource p(\ pipe-> access pipe masterbotlanda)) dataSources :: Action IO [Document] dataSources = rest =<<找到(选择[]datasources) 更新 我猜这个更漂亮了。 runDB :: Action IO a - > MCActionM(或者失败a) runDB a = do p< - lift ask liftIO $ withResource p db where db pipe = access pipe masterbotland a There are trillions of monad tutorial including the reader and it seems all clear when you read about it. But when you actually need to write, it becomes a different matter.I'v never used the Reader, just never got to it in practice. So I don't know how to go about it although I read about it.I need to implement a simple database connection pool in Scotty so every action can use the pool. The pool must be "global" and accessible by all action functions. I read that the way to do it is the Reader monad. If there are any other ways please let me know.Can you please help me and show how to do this with the Reader correctly?I'll probably learn faster if I see how it is done with my own examples.{-# LANGUAGE OverloadedStrings #-}module DB whereimport Data.Poolimport Database.MongoDB-- Get data from configip = "127.0.0.1"db = "index"--Create the connection poolpool :: IO (Pool Pipe)pool = createPool (runIOE $ connect $ host ip) close 1 300 5-- Run a database action with connection poolrun :: Action IO a -> IO (Either Failure a)run act = flip withResource (\x -> access x master db act) =<< poolSo the above is simple. and I want to use the 'run' function in every Scotty action to access the database connection pool. Now, the question is how to wrap it in the Reader monad to make it accessible by all functions? I understand that the 'pool' variable must be 'like global' to all the Scotty action functions.Thank you.UPDATEI am updating the question with the full code snippet. Where I pass the 'pool' variable down the function chain. If someone can show how to change it to utilize the monad Reader please.I don't understand how to do it.{-# LANGUAGE OverloadedStrings #-}module Main whereimport Network.HTTP.Typesimport Web.Scottyimport qualified Data.Text as Timport qualified Data.Text.Lazy as LTimport Data.Text.Lazy.Internalimport Data.Monoid (mconcat)import Data.Aeson (object, (.=), encode)import Network.Wai.Middleware.Staticimport Data.Poolimport Database.MongoDBimport Control.Monad.Trans (liftIO,lift)main = do -- Create connection pool to be accessible by all action functions pool <- createPool (runIOE $ connect $ host "127.0.0.1") close 1 300 5 scotty 3000 (basal pool)basal :: Pool Pipe -> ScottyM ()basal pool = do middleware $ staticPolicy (noDots >-> addBase "static") get "/json" (showJson pool)showJson :: Pool Pipe -> ActionM ()showJson pool = do let run act = withResource pool (\pipe -> access pipe master "index" act) d <- lift $ run $ fetch (select [] "tables") let r = either (const []) id d text $ LT.pack $ show rThanks.UPDATE 2I tried to do it the way it was suggested below but it does not work.If anyone has any ideas, please. The list of compile errors is so long that I don't even know where to begin ....main = do pool <- createPool (runIOE $ connect $ host "127.0.0.1") close 1 300 5 scotty 3000 $ runReaderT basal poolbasal :: ScottyT LT.Text (ReaderT (Pool Pipe) IO) ()basal = do middleware $ staticPolicy (noDots >-> addBase "static") get "/json" $ showJsonshowJson :: ActionT LT.Text (ReaderT (Pool Pipe) IO) ()showJson = do p <- lift ask let rdb a = withResource p (\pipe -> access pipe master "index" a) j <- liftIO $ rdb $ fetch (select [] "tables") text $ LT.pack $ show jUPDATE 3Thanks to cdk for giving the idea and thanks to Ivan Meredith for giving the scottyT suggestion. This question also helped: How do I add the Reader monad to Scotty's monadThis is the version that compiles. I hope it helps someone and saves some time.import qualified Data.Text.Lazy as Timport qualified Data.Text.Lazy.Encoding as Timport Data.Text.Lazy (Text)import Control.Monad.Readerimport Web.Scotty.Transimport Data.Poolimport Database.MongoDBtype ScottyD = ScottyT Text (ReaderT (Pool Pipe) IO)type ActionD = ActionT Text (ReaderT (Pool Pipe) IO)-- Get data from configip = "127.0.0.1"db = "basal"main = do pool <- createPool (runIOE $ connect $ host ip) close 1 300 5 let read = \r -> runReaderT r pool scottyT 3000 read read basal-- Application, meaddleware and routesbasal :: ScottyD ()basal = do get "/" shoot-- Route action handlersshoot :: ActionD ()shoot = do r <- rundb $ fetch $ select [] "computers" html $ T.pack $ show r-- Database access shortcutrundb :: Action IO a -> ActionD (Either Failure a)rundb a = do pool <- lift ask liftIO $ withResource pool (\pipe -> access pipe master db a) 解决方案 I've been trying to figure out this exact problem myself. Thanks to hints on this SO question, and other research I've come up with the following which works for me. The key bit you were missing was to use scottyTNo doubt there is a prettier way to write runDB but I don't have much experience in Haskell, so please post it if you can do better.type MCScottyM = ScottyT TL.Text (ReaderT (Pool Pipe) IO)type MCActionM = ActionT TL.Text (ReaderT (Pool Pipe) IO)main :: IO ()main = do pool <- createPool (runIOE $ connect $ host "127.0.0.1") close 1 300 5 scottyT 3000 (f pool) (f pool) $ app where f = \p -> \r -> runReaderT r papp :: MCScottyM ()app = do middleware $ staticPolicy (noDots >-> addBase "public") get "/" $ do p <- runDB dataSources html $ TL.pack $ show p runDB :: Action IO a -> MCActionM (Either Failure a) runDB a = (lift ask) >>= (\p -> liftIO $ withResource p (\pipe -> access pipe master "botland" a))dataSources :: Action IO [Document]dataSources = rest =<< find (select [] "datasources")UpdateI guess this a bit more pretty.runDB :: Action IO a -> MCActionM (Either Failure a) runDB a = do p <- lift ask liftIO $ withResource p db where db pipe = access pipe master "botland" a 这篇关于Scotty:连接池作为monad reader的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 10-11 13:43