如何在 Happstack 中创建数据库 Monad Stack?
我想创建一个可以对数据库进行大量访问的 Happstack 应用程序。我认为底部有 IO 的 Monad 堆栈和顶部类似数据库写入的 monad(中间有日志写入器)将在每次访问中具有清晰的功能,例如:
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
With:
getItemList :: MyDBMonad (Error [Item])
getItemList = do
-- etc...
但我对 Monad 知之甚少和 Monad Transformers (我认为这个问题是一个了解它的练习),我不知道如何开始创建 Database Monad,如何将 IO 从 happstack 提升到数据库堆栈,等等。
I want to create a Happstack application with lots of access to a database. I think that a Monad Stack with IO at the bottom and a Database Write-like monad on top (with log writer in the middle) will work to have a clear functions in each access, example:
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
With:
getItemList :: MyDBMonad (Error [Item])
getItemList = do
-- etc...
But I have little knowledge of Monad and Monad Transformers (I see this question as an exercise to learn about it), and I have no idea how to begin the creation of Database Monad, how to lift the IO from happstack to the Database Stack,...etc.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是一些从上面的代码片段编译而来的最小工作代码,适合像我这样困惑的新手。
您将内容放入
AppConfig
类型中,并在响应生成器中使用ask
获取它。Here is some minimal working code compiled from snippets above for confused newbies like me.
You put stuff into
AppConfig
type and grab it withask
inside your response makers.您可能想使用“ReaderT”:
Reader
monad 转换器可以使用ask
函数访问单个值 - 在这种情况下,我们希望每个人都能获得的值是数据库连接。这里,
DbHandle
是与数据库的某种连接。因为“ReaderT”已经是所有 happstack-server 类型类的实例,所以所有正常的 happstack-server 函数都将在此 monad 中工作。
您可能还需要某种帮助程序来打开和关闭数据库连接:(
在这里使用像“bracket”这样的函数可能会更好,但我不知道 ServerPart monad 有这样的操作)
我不知道不知道您想如何进行日志记录 - 您打算如何与日志文件交互?类似:
然后:
可能就足够了。然后,您可以在这些原语的基础上构建更高级别的函数。您还需要更改
runMyMonad
以在LogHandle
中传递,无论它是什么。一旦您获得了两个以上想要访问的内容,就需要使用正确的记录类型而不是元组。
You likely want to use 'ReaderT':
The
Reader
monad transformer makes a single value accessible using theask
function - in this case, the value we want everyone to get at is the database connection.Here,
DbHandle
is some connection to your database.Because 'ReaderT' is already an instance of all of the happstack-server type-classes all normal happstack-server functions will work in this monad.
You probably also want some sort of helper to open and close the database connection:
(It might be better to use a function like 'bracket' here, but I don't know that there is such an operation for the ServerPart monad)
I don't know how you want to do logging - how do you plan to interact with your log-file? Something like:
and then:
might be enough. You could then build on those primitives to make higher-level functions. You would also need to change
runMyMonad
to be passed in aLogHandle
, whatever that is.Once you get more than two things you want access to it pays to have a proper record type instead of a tuple.