首页 > 解决方案 > Haskell 中数据传输记录的通用类型

问题描述

我想与一些远程系统(可以通过 HTTP、数据库、文件等)交换数据,因此创建数据传输对象 (DTO) - 基本上,可以轻松序列化和反序列化的记录。第二步,我想将这些 DTO 映射到我的域对象。

所有 DTO 都有一个 ID 字段(例如,技术主键、消息标识符或文件名)。因为这是一种通用模式,所以我尝试以通用类型来捕捉它。这是我的第一次尝试:

data DtoShell = DtoShell
   { id :: UUID
   , dto :: Dto}

data Dto
   = MyDto1 ConcreteDto1
   | MyDto2 ConcreteDto2
   | ...

这样,与处理任意 DTO 相关的函数,因此只需要 ID,可以处理DtoShell唯一但不需要关心内部的实际数据。特定于特定 DTO 的功能可以使用它。在这两者之间,必须有一些“调度程序”函数在具体类型上进行模式匹配并选择适当的函数——例如,将具体 DTO 映射到其相应的域类型。

但是,这个方案很难扩展——如果有新的ConcreteDto3,我需要更改上面的代码,并且我需要更改“调度程序”功能。

我确实看到这似乎代表了一些更基本的问题(表达问题?我不是 CS 专业的......)。在我的搜索中,我遇到了潜在的解决方案:幻象类型、存在类型,以及最重要的类型类。但是我对 Haskell 和一般抽象 CS 的熟练程度还不够,无法评估每种方法的优缺点。因此,我有两个问题:

  1. 是否有一种普遍的、公认的做法或模式来模拟这种“可识别的记录”?例如,在访问关系数据库时。
  2. 是否有一个资源(书籍、论文、教程)可以比较不同的数据抽象方法?

标签: haskellpolymorphismdto

解决方案


为什么不直接创建一个参数化多态信封?

data Envelope a = Envelope { eid :: UUID, edata :: a } deriving (Eq, Show, Functor)

这基本上只是一个专门的对(双元组),所以你让它成为所有类型类(,)的实例。在这里,我Functor使用DeriveFunctor语言扩展使其成为一个实例。


推荐阅读