有人可以展示如何在 reader monad 中使用 snap monad 吗?单子变压器让我感到困惑。(或者,我很乐意接受有关 monad 转换器的教程的建议,以及看到光明并最终了解它们的方法。)
编辑:哎呀;忘记具体说明我实际上要做什么,而不是就特定的事情寻求帮助。战略,而不是战术。我特别想在所有处理程序之间共享一个数据库连接/池,而不必在指定路由时显式传递该数据库连接/池。似乎 reader monad 将是实现这一目标的方法。
有人可以展示如何在 reader monad 中使用 snap monad 吗?单子变压器让我感到困惑。(或者,我很乐意接受有关 monad 转换器的教程的建议,以及看到光明并最终了解它们的方法。)
编辑:哎呀;忘记具体说明我实际上要做什么,而不是就特定的事情寻求帮助。战略,而不是战术。我特别想在所有处理程序之间共享一个数据库连接/池,而不必在指定路由时显式传递该数据库连接/池。似乎 reader monad 将是实现这一目标的方法。
Snap 具有 ApplicationState 类型,允许您打包所需的任何应用程序范围的资源(数据库连接、模板引擎等)
它位于生成的文件 Application.hs 中,默认情况下 HeistState 和 TimerState 包含在 ApplicationState 中。你可以把你的数据库连接放在那里,它可以在你的 Snap 应用程序的任何地方使用。
如果你不害怕使用 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
访问阅读器数据。要在 monad 中运行一个动作Snap
,你需要将它“提升”到你的新 monad 中。
... r <- liftSnap $ ... snap action ...
不过,您可能更喜欢较短的名称。所以,也许只是snap
。
假设 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 计算。
如果你解释了你想要完成的事情,有人可能会建议一种方法来实现它。