4

有人可以展示如何在 reader monad 中使用 snap monad 吗?单子变压器让我感到困惑。(或者,我很乐意接受有关 monad 转换器的教程的建议,以及看到光明并最终了解它们的方法。)

编辑:哎呀;忘记具体说明我实际上要做什么,而不是就特定的事情寻求帮助。战略,而不是战术。我特别想在所有处理程序之间共享一个数据库连接/池,而不必在指定路由时显式传递该数据库连接/池。似乎 reader monad 将是实现这一目标的方法。

4

3 回答 3

5

Snap 具有 ApplicationState 类型,允许您打包所需的任何应用程序范围的资源(数据库连接、模板引擎等)

它位于生成的文件 Application.hs 中,默认情况下 HeistState 和 TimerState 包含在 ApplicationState 中。你可以把你的数据库连接放在那里,它可以在你的 Snap 应用程序的任何地方使用。

于 2011-02-07T03:17:28.580 回答
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)

您现在可以使用asklocal访问阅读器数据。要在 monad 中运行一个动作Snap,你需要将它“提升”到你的新 monad 中。

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

不过,您可能更喜欢较短的名称。所以,也许只是snap

于 2011-02-07T01:21:34.943 回答
0

假设 snap monad 来自http://hackage.haskell.org/packages/archive/snap-core/0.4.0/doc/html/Snap-Types.html ... Snap 是一个 monad(不是一个 monad 转换器) ,所以你不能在任意单子中运行它。如果你想要的话,你可以使用ReaderT转换器在 Snap 中嵌入 Reader 功能。

的类型runSnap

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

这告诉我们它在一个Iteratee ByteString IO单子中运行。Reader monad 不允许您执行 IO 或迭代输入流,因此您无法在 Reader monad 中运行 Snap 计算。

如果你解释了你想要完成的事情,有人可能会建议一种方法来实现它。

于 2011-02-06T23:58:39.577 回答