[英]Haskell: “how much” of a type should functions receive? and avoiding complete “reconstruction”
I've got these data types: 我有这些数据类型:
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)
It's the base datatype for characters, enemies, objects, etc. in my game (well, I just have two rectangles as the player and the ground right now :p). 它是我游戏中角色,敌人,物体等的基本数据类型(好吧,我现在只有两个矩形作为玩家和地面:p)。
When a key, the characters moves right, left or jumps by changing its velocity
. 当一个键时,字符通过改变其
velocity
向右,向左或跳跃。 Moving is done by adding the velocity
to the coords
. 通过将
velocity
添加到coords
来完成移动。 Currently, it's written as follows: 目前,它的编写如下:
move (PointPlus (x, y) (xi, yi)) = PointPlus (x + xi, y + yi) (xi, yi)
I'm just taking the PointPlus
part of my Body
and not the entire Body
, otherwise it would be: 我只是把
PointPlus
作为我Body
一部分,而不是整个Body
,否则它将是:
move (Body (BodyGeo (PointPlus (x, y) (xi, yi)) wh) col) = (Body (BodyGeo (PointPlus (x + xi, y + yi) (xi, yi)) wh) col)
Is the first version of move
better? move
的第一个版本更好吗? Anyway, if move
only changes PointPlus
, there must be another function that calls it inside a new Body
. 无论如何,如果
move
只改变了PointPlus
,那么必须有另一个函数在一个新的Body
中调用它。 I explain: there's a function update
which is called to update the game state; 我解释一下:有一个函数
update
被调用来更新游戏状态; it is passed the current game state, a single Body
for now, and returns the updated Body
. 它传递给当前游戏状态,现在是一个
Body
,并返回更新的Body
。
update (Body (BodyGeo (PointPlus xy (xi, yi)) wh) pict) = (Body (BodyGeo (move (PointPlus xy (xi, yi))) wh) pict)
That tickles me. 这让我感到痒痒。 Everything is kept the same within
Body
except the PointPlus
. 除
PointPlus
外, Body
内的所有内容都保持不变。 Is there a way to avoid this complete "reconstruction" by hand? 有没有办法避免手工完成“重建”? Like in:
像:
update body = backInBody $ move $ pointPlus body
Without having to define backInBody
, of course. 当然,无需定义
backInBody
。
You're looking for "lenses". 你正在寻找“镜头”。 There are several different packages for lenses;
镜片有几种不同的包装; here is a good summary of them.
这是对它们的一个很好的总结。
My understanding is that a lens on a data type a
for some field b
provides two operations: a way to get the value of b
and a way to get a new a
with a different value of b
. 我的理解是,在一个数据类型的镜头
a
对一些领域b
提供了两个操作:一种方式来获得的值b
和一种方式来获得一个新的a
具有不同的值b
。 So you would just use a lens to work with the deeply nested PointPlus
. 因此,您只需使用镜头即可使用深度嵌套的
PointPlus
。
The lens packages provide useful functions for working with lenses as well as ways of generating lenses automatically (with template Haskell) which could be very convenient. 镜头包提供了与镜头一起使用的有用功能以及自动生成镜头的方法(使用模板Haskell),这可能非常方便。
I think they are worth looking into for your project, especially because you are likely to encounter similar problems with nesting in other places thanks to the structure of your data types. 我认为他们值得研究您的项目,特别是因为您的数据类型结构可能会遇到类似的嵌套问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.