7

我有一些基本上像这样结构的记录类型:

type Body x = { x | pos: (Int,Int) }
type Bubble = Body { radius: Int }
type Box = Body { width: Int, height: Int }

现在我想要一个混合列表中的任何一个,并在Body零件上执行一些操作,但仍然是特殊情况处理BoxBubble其他时间。例如,具有(省略了实现):

mv: (Int,Int) -> Body a -> Body a
bubble: Bubble
box: Box

我想

map (mv (1,1)) [box,bubble]

但这失败了,因为 Elm 认为列表中的类型不兼容。

Box现在我可以像这样将es 和s包装Bubble在 ADT 中:

type BodyWrap = BoxWrap Box | BubbleWrap Bubble

但随后我需要在每种情况下都进行解包和重新包装。如果我想折叠混合列表,它会变得更加混乱。这个 gist中有一个例子。

有没有更优雅的方式来处理这种情况?

4

1 回答 1

9

当使用组合而不是继承时,这个问题就消失了。

不要将整个结构包装在 ADT 中,而是让记录中的一个字段包含具有对象特定属性的 ADT:

type Body = { pos: (Int,Int), shape: Shape }
data shape = Bubble Int | Box (Int,Int)

这允许仅在必要时Body在匹配时使用共享结构。shape

于 2014-08-14T13:52:55.467 回答