我有这些数据类型:
data PointPlus = PointPlus
{ coords :: Point
, velocity :: Vector
} deriving (Eq)
data BodyGeo = BodyGeo
{ pointPlus :: PointPlus
, size :: Point
} deriving (Eq)
data Body = Body
{ geo :: BodyGeo
, pict :: Color
} deriving (Eq)
它是我游戏中角色、敌人、物体等的基本数据类型(好吧,我现在只有两个矩形作为玩家和地面:p)。
当一个键时,字符通过改变它的
velocity
来向右、向左或跳跃。 .通过添加 velocity
来完成移动。到coords
.目前,它的编写如下:move (PointPlus (x, y) (xi, yi)) = PointPlus (x + xi, y + yi) (xi, yi)
我只是服用
PointPlus
我的一部分Body
而不是整个 Body
,否则它将是:move (Body (BodyGeo (PointPlus (x, y) (xi, yi)) wh) col) = (Body (BodyGeo (PointPlus (x + xi, y + yi) (xi, yi)) wh) col)
是
move
的第一个版本更好的?无论如何,如果 move
仅更改 PointPlus
,必须有另一个函数在新的 Body
中调用它.我解释一下:有一个函数update
调用它来更新游戏状态;它传递当前游戏状态,单个Body
现在,并返回更新后的 Body
.update (Body (BodyGeo (PointPlus xy (xi, yi)) wh) pict) = (Body (BodyGeo (move (PointPlus xy (xi, yi))) wh) pict)
这让我很痒。
Body
内的一切都保持不变除了 PointPlus
.有没有办法手动避免这种完全的“重建”?像:update body = backInBody $ move $ pointPlus body
无需定义
backInBody
, 当然。
最佳答案
您正在寻找“镜头”。镜头有几种不同的包装; here是对它们的一个很好的总结。
我的理解是数据类型 a
的镜头对于某些领域b
提供两种操作:一种获取b
的值的方法以及获得新 a
的方法具有不同的值 b
.因此,您只需使用镜头来处理深度嵌套的 PointPlus
.
镜头包提供了使用镜头的有用功能以及自动生成镜头的方法(使用模板 Haskell),这非常方便。
我认为它们值得为您的项目研究,特别是因为由于数据类型的结构,您可能会在其他地方遇到类似的嵌套问题。
关于function - Haskell:函数应该接收的类型为 "how much"?并避免完整的 "reconstruction",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10967832/