有人可以展示如何在阅读器monad中使用snap monad吗? Monad变形金刚迷惑我。 (或者,我很乐意接受有关monad变换器的教程的建议,以及查看光线并最终了解它们的方法。)
编辑:糟糕;忘了说明我实际上要做的事情,而不是寻求特定事情的帮助。战略,而不是战术。我特别希望在所有处理程序之间共享数据库连接/池,而不必在指定路由时显式传递该数据库连接/池。似乎读者monad将是实现这一目标的方法。
答案 0 :(得分:5)
Snap具有ApplicationState类型,允许您打包所需的任何应用程序范围的资源(数据库连接,模板引擎等)。
它位于生成的文件Application.hs中,默认情况下将HeistState和TimerState包含在ApplicationState中。您可以将数据库连接放在那里,它可以在Snap应用程序的任何位置使用。
答案 1 :(得分:4)
如果您不害怕使用特定于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)
您现在可以使用ask
和local
来访问阅读器数据。要在Snap
monad中执行操作,您需要将其“提升”到新的monad中。
... r <- liftSnap $ ... snap action ...
但您可能更喜欢较短的名字。所以,也许只是snap
。
答案 2 :(得分:0)
假设snap monad来自http://hackage.haskell.org/packages/archive/snap-core/0.4.0/doc/html/Snap-Types.html ... Snap是monad(不是monad变换器),所以你不能在任意monad中运行它。您可以使用ReaderT
转换器在Snap中嵌入Reader功能,如果这是您想要的。
runSnap
的类型是
runSnap :: Snap a -> (ByteString -> IO ()) -> (Int -> IO ()) -> Request -> Iteratee ByteString IO (Request, Response)
告诉我们它以Iteratee ByteString IO
monad运行。 Reader monad不允许您对输入流执行IO或迭代,因此您无法在Reader monad中运行Snap计算。
如果你解释你想要完成什么,有人可能会建议一种方法来实现它。