Handling records with shared substructure in Elm

陌路散爱 提交于 2019-12-07 06:21:46

问题


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 }

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

I would like to

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

but this fails because Elm deems the types in the list incompatible.

Now I could wrap the Boxes and Bubbles 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?


回答1:


This problem goes away when using composition rather than inheritance.

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)

This allows using the shared structure in Body while matching on shape only when necessary.



来源:https://stackoverflow.com/questions/25129110/handling-records-with-shared-substructure-in-elm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!