替代代数数据类型,记录语法中有许多构造函数



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

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

截至目前,我有一种具有不同构造函数的数据类型:

data Element = Sun {
  elemColorStart :: Color,
  elemColorEnd :: Color,
  elemCoords :: Coords,
  elemPeriod :: Float,
  elemSize :: Float,
  elemSteps :: Step,
  elemTime :: Float
}
| Cloud {
  elemKind :: CloudKind,
  elemColorMain :: Color,
  elemCoords :: Coords,
  elemRans :: [Float],
  elemSize' :: Size',
  elemSteps :: Step,
  elemTime :: Float
}
... etc

或者,我可以有一个具有所有可能属性的通用构造函数,如果不需要它们,则不初始化它们,尽管这看起来更糟。

这看起来不是很"Haskelly",事实上这种方法总的来说是面向对象的。我做错了什么?欢迎任何其他可能的办法;这不是作业,所以我真的没有任何限制。

将事物隔离到它们自己的数据类型中,并且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,也可以为关注点分离带来的所有好处提供专用 API。

哦,顺便说一句,我已经删除了字段名称的前缀,因为现在我们有DuplicateRecordFields扩展名。

顺便说一句,你会发现这个问题很有用。

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

最新更新