简体   繁体   English

使用快照中的阅读器monad(或快照中的monad变换器)

[英]Using the reader monad in snap (or, monad transformers in snap)

Can someone show how to use the snap monad inside the reader monad? 有人可以展示如何在阅读器monad中使用snap monad吗? Monad transformers confuse me. Monad变形金刚迷惑我。 (Alternatively, I will gladly accept suggestions of tutorials about monad transformers, and ways to see the light and finally grok them.) (或者,我很乐意接受有关monad变换器的教程的建议,以及查看光线的方法,并最终了解它们。)

Edit: Oops; 编辑:糟糕; forgot to specify what I'm actually trying to do, instead of asking for help with a specific thing. 忘了说明我实际上要做的事情,而不是寻求特定事情的帮助。 Strategy, not tactics. 战略,而不是战术。 I specifically want to share a database connection/pool amongst all handlers, without having to explicitly pass that database connection/pool when specifying routes. 我特别希望在所有处理程序之间共享数据库连接/池,而不必在指定路由时显式传递该数据库连接/池。 It seems that the reader monad would be the way to accomplish that. 似乎读者monad将是实现这一目标的方法。

Snap has ApplicationState type that allows you package whatever application wide resources you need (db connections, template engines etc.) Snap具有ApplicationState类型,允许您打包所需的任何应用程序范围的资源(数据库连接,模板引擎等)

It is located in generated file Application.hs and by default has HeistState and TimerState included into ApplicationState. 它位于生成的文件Application.hs中,默认情况下将HeistState和TimerState包含在ApplicationState中。 You can just put your db connection there and it will be available from anywhere in your Snap application. 您可以将数据库连接放在那里,它可以在Snap应用程序的任何位置使用。

If you're not afraid to use GHC-specific extensions, here's the no-frills approach to monad transformers: 如果你不害怕使用GHC特定的扩展,这里是monad变换器的简单方法:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import Control.Monad.Reader

data ReaderData = ...

newtype MyMonad a = MyMonad (ReaderT ReaderData Snap a)
  deriving (Monad, MonadReader ReaderData)

runMyMonad :: MyMonad a -> ReaderData -> Snap a
runMyMonad (MyMonad m) r = runReaderT m r

liftSnap :: Snap a -> MyMonad a
liftSnap act = MyMonad (lift act)

You can now use ask and local to access the reader data. 您现在可以使用asklocal来访问阅读器数据。 To run an action in the Snap monad, you need to "lift" it into your new monad. 要在Snap monad中运行一个动作,你需要将它“提升”到你的新monad中。

... r <- liftSnap $ ... snap action ...

You may prefer a shorter name, though. 不过,您可能更喜欢较短的名字。 So, maybe just snap . 所以,也许只是snap

Assuming the snap monad is from http://hackage.haskell.org/packages/archive/snap-core/0.4.0/doc/html/Snap-Types.html ... Snap is a monad (not a monad transformer), so you cannot run it inside an arbitrary monad. 假设snap monad来自http://hackage.haskell.org/packages/archive/snap-core/0.4.0/doc/html/Snap-Types.html ... Snap是monad(不是monad变换器) ,所以你不能在任意monad中运行它。 You could use the ReaderT transformer to embed Reader functionality inside Snap, if that's what you want. 您可以使用ReaderT转换器在Snap中嵌入Reader功能,如果这是您想要的。

The type of runSnap is runSnap的类型是

runSnap :: Snap a -> (ByteString -> IO ()) -> (Int -> IO ()) -> Request -> Iteratee ByteString IO (Request, Response)

which tells us that it runs in an Iteratee ByteString IO monad. 它告诉我们它运行在Iteratee ByteString IO monad中。 A Reader monad does not let you do IO or iterate over an input stream, so you cannot run a Snap computation in a Reader monad. Reader monad不允许您对输入流执行IO或迭代,因此您无法在Reader monad中运行Snap计算。

If you explain what you want to accomplish, someone may be able to suggest a way to achieve it. 如果你解释你想要完成什么,有人可能会建议一种方法来实现它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM