用于数据库抽象的惯用Haskell

9
在面向对象编程语言中,我可能会编写一个数据库包装器,它封装了数据库连接、管理模式并提供几个核心操作,如exec, query, prepare_and_execute。我甚至可能会有一个单独的数据库帮助类,它将处理数据库模式,使数据库抽象仅处理连接。这将由模型包装器/工厂使用数据库抽象类来创建模型类的实例。类似于这样的UML图: 在惯用的Haskell设计中,设计这样的系统应该采用哪种方式?

1
也许值得一看 http://blog.ezyang.com/2010/06/databases-are-categories/。 - Alexandre C.
@Alexandre 谢谢,很有收获,但我不认为这就是我要找的 :) - Masse
2
你的图表已经不存在了。你能再次上传吗?这个问题很大程度上取决于它。 - Tim Post
2个回答

5
在Haskell中最常用的数据库抽象库是HDBC。这意味着查询仅表示为带有占位符的String。较少的人使用HaskellDB,它提供了一种类型安全的方式来构建查询。没有禁止使用用户数据类型来表示常见查询和自定义函数来构建它们。
在Haskell中,值是不可变的,这意味着将记录对应的可变对象与数据库进行关联是没有意义的。相反,我认为更常见的做法是定义用户数据类型和函数,以将这些类型的值推入/拉出数据库。
每当需要进行数据库更新时,它们很可能在某个有状态的单子下运行IO。这将允许保持连接打开,例如,在请求之间执行某些操作。
最后,函数是一等公民,因此可以动态构建所有函数。因此,函数本身可以封装您想要的任何信息。
因此,我认为,通常的Haskell方法包括:
  • 代数数据类型用于表示实际数据(作为不可变值)
  • 应用的其余部分用于转换这些值
  • 生成查询的函数(封装模式细节,将数据编组到/从Haskell数据类型)
  • (可选)有状态的monad用于运行查询(隐藏数据库访问的详细信息)
  • 运行查询的函数(隐藏数据库访问的详细信息)

我之前也有类似的想法。你能详细说明一下“一个有状态的单子来运行查询”的部分吗?之前我写过一个 HDBC 的概念证明抽象,其中我使用了 Reader 单子来隐藏连接细节(runDatabase 会建立连接,用连接值运行 reader,然后关闭连接)。我还有表示 Person 和 Location 的 ADT,以及像“getLocation :: Int -> IO Location”和“getPerson :: Int -> IO Person”这样的函数。对于修改数据库,我有类似“savePerson :: Person -> IO ()”这样的函数。这是你所想的吗? - Masse
@Masse 我的意思是,如果你想编译一些或所有语句,你可以在它们上面运行prepare,并且你需要一个地方在查询之间保存已编译的语句。因此,您可以使用type DB a = StateT [(Query, Statement)] IO a来保存它们(我假设语句由自定义的“Query”数据类型表示,该类型实现了“Eq”)。在顶层,我会有类似于runDB :: FilePath -> DB a -> IO awithPerson :: Query -> Key -> (Person -> (a, Maybe Person)) -> DB a... - sastanin

2
使用Haskell处理数据库最常见和最有效的方法,我认为,是将记录缓存在内存中,并使用STM进行内存事务,以便您可以使用数据库进行存储。然后,您可以使用事务变量(TVar)来管理记录。但是,您必须定义自己的查询语言,并且需要一种缓存/取消缓存和同步的机制。这毕竟就是Java EJB3和Hybernate所做的事情。
包TCache定义了DBRefs,这是具有TVar语义的持久化STM变量。它们可以成为记录的一部分,并指向另一个记录,而且非常轻量级,因此您可以开发自己的抽象。它还具有类似于SQL的查询语言,包括字段搜索、连接和全文搜索等功能。它默认以文件形式进行持久化。您只需要为Haskell记录定义一个键,就可以实现文件持久化。对于数据库持久化,有一个IResource类,您可以在其中定义记录的读取、写入和删除操作。每个记录都可以有自己的持久性。因此,所有数据库交互都在源代码的单个位置中,内存事务速度快得多。TCache每次异步写入数据库时都会写入一致状态。它也可以同步写入。

感觉这里有一个严重的NIF综合症,无法控制。 - Masse
NIF综合症是什么意思?如果您不明白我的意思,请向我询问澄清。如果您不感兴趣,简单地说声谢谢或保持沉默就足够了。如果您对我的回答感到不舒服,可以喝杯茶放松一下。 - agocorona

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接