在Elm中处理具有共享子结构的记录 [英] Handling records with shared substructure in Elm
问题描述
我有一些基本上像这样的记录类型:
I have some record types structured essentially like this:
type Body x = { x | pos: (Int,Int) }
type Bubble = Body { radius: Int }
type Box = Body { width: Int, height: Int }
现在,我想将所有这些混合在一起,并在Body
部分上执行一些操作,但在其他时候还是特殊情况下处理Box
和Bubble
.例如,(取消实现):
Now I would like to have a mixed list of any of these and perform some operation on the Body
part, but still special case handling Box
and Bubble
other times. For example, having (implementations elided):
mv: (Int,Int) -> Body a -> Body a
bubble: Bubble
box: Box
我想
map (mv (1,1)) [box,bubble]
但这失败了,因为Elm认为列表中的类型不兼容.
but this fails because Elm deems the types in the list incompatible.
现在,我可以将Box
es和Bubble
s包裹在ADT中,如下所示:
Now I could wrap the Box
es and Bubble
s in an ADT like so:
type BodyWrap = BoxWrap Box | BubbleWrap Bubble
但是然后我需要在每种情况下都进行拆包和重新包装.如果我想在混合清单上折,它会变得更加混乱. 此要点.
but then I need to do an unwrapping and rewrapping in every case. If I want to fold on the mixed list it gets even messier. An example is in this gist.
有没有更优雅的方式来处理这种情况?
Is there a more elegant way of handling this situation?
推荐答案
使用组合而不是继承时,此问题就消失了.
This problem goes away when using composition rather than inheritance.
不是将整个结构包装在ADT中,而是使记录中的一个字段容纳具有对象特定属性的ADT:
Instead of wrapping the whole structure in an ADT, make one field in the record hold an ADT with the object-specific properties:
type Body = { pos: (Int,Int), shape: Shape }
data shape = Bubble Int | Box (Int,Int)
这允许使用Body
中的共享结构,同时仅在必要时在shape
上进行匹配.
This allows using the shared structure in Body
while matching on shape
only when necessary.
这篇关于在Elm中处理具有共享子结构的记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!