首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Happstack中创建数据库Monad Stack?

如何在Happstack中创建数据库Monad Stack?
EN

Stack Overflow用户
提问于 2011-10-18 19:33:11
回答 2查看 865关注 0票数 5

我想创建一个可以大量访问数据库的Happstack应用程序。我认为底部有IO的Monad Stack和顶部的类似Database Write的monad (中间有日志写入器)将在每个访问中具有明确的功能,例如:

代码语言:javascript
复制
itemsRequest :: ServerConfig -> ServerPart Response
itemsRequest cf = dir "items" $ do
  methodM [GET,HEAD]
  liftIO $ noticeM (scLogger cf) "sended job list"

  items <- runDBMonad (scDBConnString cf) $ getItemLists

  case items of
    (Right xs) -> ok $ toResponse $ show xs
    (Left err) -> internalServerError $ toResponse $ show err

通过以下方式:

代码语言:javascript
复制
getItemList :: MyDBMonad (Error [Item])
getItemList = do
  -- etc...

但我对Monad和Monad Transformers知之甚少(我认为这个问题是学习它的一个练习),我不知道如何开始创建数据库Monad,如何将IO从happstack提升到数据库堆栈,...etc。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-10-19 20:32:38

你可能想要使用'ReaderT':

代码语言:javascript
复制
type MyMonad a = ReaderT DbHandle ServerPart a

通过使用ask函数,Reader monad转换器可以访问单个值-在本例中,我们希望每个人都能获得的值是数据库连接。

在这里,DbHandle是到您的数据库的一些连接。

因为'ReaderT‘已经是所有happstack server类型类的一个实例,所以所有正常的happstack server函数都将在这个monad中工作。

您可能还需要某种帮助器来打开和关闭数据库连接:

代码语言:javascript
复制
runMyMonad :: String -> MyMonad a -> ServerPart a
runMyMonad connectionString m = do
   db <- liftIO $ connect_to_your_db connectionString
   result <- runReaderT m db
   liftIO $ close_your_db_connection db

(在这里使用像'bracket‘这样的函数可能更好,但我不知道ServerPart monad是否有这样的操作)

我不知道你想如何做日志记录--你打算如何与你的日志文件交互?类似于:

代码语言:javascript
复制
type MyMonad a = ReaderT (DbHandle, LogHandle) ServerPart a

然后:

代码语言:javascript
复制
askDb :: MyMonad DbHandle
askDb = fst <$> ask

askLogger :: MyMonad LogHandle
askLogger = snd <$> ask

可能就够了。然后,您可以在这些原语的基础上构建更高级别的函数。您还需要将runMyMonad更改为在LogHandle中传递,无论它是什么。

一旦你得到了两个以上你想要访问的东西,拥有一个合适的记录类型而不是一个元组是值得的。

票数 6
EN

Stack Overflow用户

发布于 2012-06-21 21:44:14

这是一些从上面的代码片段编译而来的最小工作代码,适用于像我这样困惑的新手。

您可以将内容放入AppConfig类型中,并在响应生成器中使用ask来获取它。

代码语言:javascript
复制
{-# LANGUAGE OverloadedStrings #-}
module Main where

import Happstack.Server
import Control.Monad.Reader
import qualified Data.ByteString.Char8 as C

myApp :: AppMonad Response
myApp = do
    -- access app config. look mom, no lift!
    test <- ask

    -- try some happstack funs. no lift either.
    rq <- askRq
    bs <- lookBS "lol"

    -- test IO please ignore
    liftIO . print $ test
    liftIO . print $ rq
    liftIO . print $ bs

    -- bye
    ok $ toResponse ("Oh, hi!" :: C.ByteString)

-- Put your stuff here.
data AppConfig = AppConfig { appSpam :: C.ByteString
                           , appEggs :: [C.ByteString] } deriving (Eq, Show)
config = AppConfig "THIS. IS. SPAAAAAM!!1" []

type AppMonad = ReaderT AppConfig (ServerPartT IO)

main = simpleHTTP (nullConf {port=8001}) $ runReaderT myApp config {appEggs=["red", "gold", "green"]}
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7806554

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档