haskell - 事务类型安全

标签 haskell

我有一个 Transaction monad,如下所示:

newtype Transaction t m a = .. 我的 monad 堆栈在这里 ..

t 是一个虚拟类型,我用它来确保我链接的交易适用于同一个后端存储。

我的主循环的迭代使用如下类型:

Transaction DB IO (Widget (Transaction DB IO ()))

上述类型表示:“生成 UI 小部件的事务,其用户输入转换为要执行的事务”。

此外,我还有:

数据属性 m a = Property { get::m a, set::a -> m () }

这非常有用(尤其是因为它能够与 FCLabel 组合。

我大量使用 Property (Transaction t m) 来生成我的交易。

现在,我希望类型系统保证生成Widget的Transaction是只读事务,Widget生成的事务允许是读写事务。

显然,我可以向交易中添加另一个虚拟类型,但这有两个问题:

  • 这将需要从 Transaction ReadOnlyTransaction ReadWrite 的显式转换或类型类 hackery 以允许读取和写入原语之间的单子(monad)组合。这个我觉得我可以解决。

  • 为了包含编写器,属性数据构造器始终需要读/写操作,这会强制“m”成为读写事务。我将无法在读写和只读事务的上下文中重复使用属性。

我正在寻找一种在不丢失上述设计特征的情况下获得上述类型安全性的好方法。

最佳答案

如果您希望类型检查器强制区分只读和读写事务,那么这两者必须是不同的类型。从那里开始,这个解决方案就出现了:

data Property rm wm a = Property { get :: rm a, set :: a -> wm () }

这种方法有很多变体。您可以拥有一个具有不同上下文参数的 monad,而不是不同的 monad:

newtype Transaction t c m a = .. my monad stack here

data Property mc c1 c2 a = Property { get :: mc c1 a, set :: a -> mc c2 () }

这里 mc 是一个 monad 构造器;它需要 context 参数来制作 monad。尽管这使用了更多参数,但我更喜欢它,因为它强调了 monad 的相似性。

对于需要读取或写入的函数,请考虑使用类型类。

newtype ReadOnly = ReadOnly

newtype ReadWrite = ReadWrite

class ReadContext rm where

class WriteContext rm where

instance ReadContext ReadOnly where
instance ReadContext ReadWrite where

instance WriteContext ReadWrite where

someGetter :: ReadContext c => Transaction t c m a

someSetter :: WriteContext c => a -> Transaction t c m ()

这应该会限制您需要执行的转换/提升操作的数量,同时仍然强制执行类型安全。

关于haskell - 事务类型安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3314148/

相关文章:

haskell - 通过累积添加另一个列表的元素来创建列表 : Haskell

haskell - 如何在 Haskell 中连接幻像类型中的元组?

haskell - 如何将多态函数应用于动态值

haskell - 使用GHCJS编译示例程序时未找到Lens

haskell - 使用 Yesod 的 Persistent 存储现有数据类型

performance - Prolog 有像 Haskell 一样的别名 "operator"吗?

haskell - 将 Data.Time.UTCTime 与 ByteString 相互转换

haskell - typeOf 返回类型

Haskell euclid算法两个整数的最大公约数

haskell - Double 和 Integral 类型之间的重叠实例