Haskell 中数据传输记录的通用类型
Generic type for data transfer records in Haskell
我想与一些远程系统交换数据(可以通过 HTTP、数据库、文件等),因此创建数据传输对象 (DTO) - 基本上是可以轻松序列化和反序列化的记录。在第二步中,我想将这些 DTO 映射到我的域对象。
所有 DTO 都有一个 ID 字段(例如,技术主键、消息标识符或文件名)。因为这是一个通用模式,所以我尝试用一个通用类型来捕捉它。这是我的第一次尝试:
data DtoShell = DtoShell
{ id :: UUID
, dto :: Dto}
data Dto
= MyDto1 ConcreteDto1
| MyDto2 ConcreteDto2
| ...
这样,涉及处理任意DTO的函数,因此只需要ID,可以只处理DtoShell
而不需要关心里面的实际数据。特定 DTO 特有的功能可以与之配合使用。在这两者之间,必须有一些 "dispatcher" 函数在具体类型上进行模式匹配并选择适当的函数 - 例如,将具体 DTO 映射到其相应的域类型。
然而,这个方案很难扩展——如果有新的ConcreteDto3
,我需要改变上面的代码,我需要改变"dispatcher"函数。
我确实看到这似乎是一些更基本问题的表现(表达问题?我不是CS专业的......)。在我的搜索中,我遇到了潜在的解决方案:Phantom 类型、存在类型,以及最重要的类型类。但是我对 Haskell 和一般抽象 CS 还不够熟练,无法评估每种方法的优缺点。因此,我有两个问题:
- 是否有通用的、公认的做法或模式来建模这样的 "identifiable records"?例如,访问关系数据库时。
- 是否有单一资源(书籍、论文、教程)比较不同的数据抽象方法?
为什么不直接创建一个参数多态包络?
data Envelope a = Envelope { eid :: UUID, edata :: a } deriving (Eq, Show, Functor)
这基本上只是一个特殊的对(二元组),因此您将它作为 (,)
是 类 的所有类型的实例。在这里,我使用 DeriveFunctor
语言扩展将其设为 Functor
实例。
我想与一些远程系统交换数据(可以通过 HTTP、数据库、文件等),因此创建数据传输对象 (DTO) - 基本上是可以轻松序列化和反序列化的记录。在第二步中,我想将这些 DTO 映射到我的域对象。
所有 DTO 都有一个 ID 字段(例如,技术主键、消息标识符或文件名)。因为这是一个通用模式,所以我尝试用一个通用类型来捕捉它。这是我的第一次尝试:
data DtoShell = DtoShell
{ id :: UUID
, dto :: Dto}
data Dto
= MyDto1 ConcreteDto1
| MyDto2 ConcreteDto2
| ...
这样,涉及处理任意DTO的函数,因此只需要ID,可以只处理DtoShell
而不需要关心里面的实际数据。特定 DTO 特有的功能可以与之配合使用。在这两者之间,必须有一些 "dispatcher" 函数在具体类型上进行模式匹配并选择适当的函数 - 例如,将具体 DTO 映射到其相应的域类型。
然而,这个方案很难扩展——如果有新的ConcreteDto3
,我需要改变上面的代码,我需要改变"dispatcher"函数。
我确实看到这似乎是一些更基本问题的表现(表达问题?我不是CS专业的......)。在我的搜索中,我遇到了潜在的解决方案:Phantom 类型、存在类型,以及最重要的类型类。但是我对 Haskell 和一般抽象 CS 还不够熟练,无法评估每种方法的优缺点。因此,我有两个问题:
- 是否有通用的、公认的做法或模式来建模这样的 "identifiable records"?例如,访问关系数据库时。
- 是否有单一资源(书籍、论文、教程)比较不同的数据抽象方法?
为什么不直接创建一个参数多态包络?
data Envelope a = Envelope { eid :: UUID, edata :: a } deriving (Eq, Show, Functor)
这基本上只是一个特殊的对(二元组),因此您将它作为 (,)
是 类 的所有类型的实例。在这里,我使用 DeriveFunctor
语言扩展将其设为 Functor
实例。