在Elm中处理具有共享子结构的记录

Jus*_*ser 5 polymorphism algebraic-data-types elm

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

type Body x = { x | pos: (Int,Int) }
type Bubble = Body { radius: Int }
type Box = Body { width: Int, height: Int }
Run Code Online (Sandbox Code Playgroud)

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

mv: (Int,Int) -> Body a -> Body a
bubble: Bubble
box: Box
Run Code Online (Sandbox Code Playgroud)

我想要

map (mv (1,1)) [box,bubble]
Run Code Online (Sandbox Code Playgroud)

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

现在我可以将Boxes和Bubbles 包装在ADT中,如下所示:

type BodyWrap = BoxWrap Box | BubbleWrap Bubble
Run Code Online (Sandbox Code Playgroud)

但是我需要在每种情况下进行解包和重新打包.如果我想在混合列表上折叠,它会变得更加混乱.这个要点就是一个例子.

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

Jus*_*ser 7

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

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

type Body = { pos: (Int,Int), shape: Shape }
data shape = Bubble Int | Box (Int,Int)
Run Code Online (Sandbox Code Playgroud)

这允许Bodyshape仅在必要时匹配时使用共享结构.