Haskell中数据传输记录的通用类型。

问题描述 投票:2回答:1

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

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

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

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

这样一来,那些处理任意DTO的函数 只需要ID,就可以处理这些东西 DtoShell但不需要关心里面的实际数据。具体的DTO所特有的函数可以与之配合。在这两者之间,必须有一些 "调度器 "函数,在具体类型上进行模式匹配,并选择合适的函数--例如,将一个具体的DTO映射到其对应的域类型。

然而,这个方案很难扩展--如果有一个新的 ConcreteDto3,我需要修改上面的代码,我需要修改 "dispatcher "函数。

我确实看到,这似乎是一些更基本的问题的表示(表达式问题?我不是CS专业的...)。在我的搜索中,我遇到了潜在的解决方案。幻象类型, 存在类型, 还有, 最重要的, 类型类. 但我对 Haskell 和一般抽象 CS 还不够精通,无法评估每种方法的利弊。因此,我有两个问题。

  1. 有没有一种通用的、公认的做法或模式 来模拟这种 "可识别的记录"?比如,在访问关系型数据库时。
  2. 有没有一种资源(书籍、论文、教程)可以比较不同的数据抽象方法?
haskell polymorphism dto
1个回答
3
投票

为什么不直接创建一个参数化的多态包络呢?

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

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

© www.soinside.com 2019 - 2024. All rights reserved.