记录语法中具有大量构造函数的代数数据类型的替代方法

时间:2019-03-31 18:19:51

标签: haskell record algebraic-data-types

我有一个自定义数据类型,用于包含景观元素(云,太阳,山等)。我需要列出它们,所以我不能使用不同的类型和通用的类型类。

它们共享构造函数中的大多数字段,但是有些具有其他属性(例如,如果云是否下雨)。

到目前为止,我有一种具有不同构造函数的数据类型:

df<-read.table(text="Id Rat1    Rat2    Rat3    Rat4    Time1   Time2   Time3   Time4
 1  4   5   11  16  15  18  19  17
 2  5   5   11  16  18  18  14  13
 3  3   6   10  15  12  16  17  12
 4  4   6   12  17  16  20  17  15
 ", h=T)

或者,我可以有一个具有所有可能属性的通用构造函数,并且即使不需要这些属性,也不必初始化它们。

这看起来不太“ Haskelly”,实际上,这种方法通常是面向对象的。 我在做什么错了?任何其他可能的方法都会受到欢迎;这不是一项任务,所以我实际上没有任何约束。

2 个答案:

答案 0 :(得分:9)

将事物隔离为自己的数据类型,并将Element作为它们的总和:

data Sun = Sun {
  colorStart :: Color,
  colorEnd :: Color,
  coords :: Coords,
  period :: Float,
  size :: Float,
  steps :: Step,
  time :: Float
}

data Cloud = Cloud {
  kind :: CloudKind,
  colorMain :: Color,
  coords :: Coords,
  rans :: [Float],
  size :: Size',
  steps :: Step,
  time :: Float
}

data Element = SunElement Sun | CloudElement Cloud

现在,您可以拥有专用的API,以解决与关注点分离相关的所有美好事物。

哦,顺便说一句,由于我们现在有了DuplicateRecordFields扩展名,我已经在字段名称上添加了前缀。

顺便说一句,您会发现this question有用。

答案 1 :(得分:0)

Nikita答案的一个转折是使用称为Shared的ADT来保存在SunCloud中都存在的字段。如果需要,可以将此与从OO继承进行比较。

data Shared = Shared {       
  coords :: Coords,     
  steps :: Step,
  time :: Float
}

data Sun = Sun {
  colorStart :: Color,
  colorEnd :: Color,
  period :: Float,
  size :: Float,
  shared :: Shared
}

data Cloud = Cloud {
  kind :: CloudKind,
  colorMain :: Color, 
  rans :: [Float],
  size :: Size',
  shared :: Shared
}

data Element = SunElement Sun | CloudElement Cloud