Function 哈斯凯尔:“这是一个很好的例子。”;“多少钱?”;函数应该接收的类型?并避免“完全的”;重建“;
我有以下数据类型:Function 哈斯凯尔:“这是一个很好的例子。”;“多少钱?”;函数应该接收的类型?并避免“完全的”;重建“;,function,haskell,types,Function,Haskell,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 ::
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)
当按下一个键时,字符会向右、向左移动或通过更改其速度进行跳跃。移动是通过将速度
添加到坐标
来完成的。目前,其内容如下:
move (PointPlus (x, y) (xi, yi)) = PointPlus (x + xi, y + yi) (xi, yi)
我只是取我的正文的部分,而不是整个正文,否则它将是:
move (Body (BodyGeo (PointPlus (x, y) (xi, yi)) wh) col) = (Body (BodyGeo (PointPlus (x + xi, y + yi) (xi, yi)) wh) col)
move
的第一个版本更好吗?无论如何,如果move
仅更改PointPlus
,则必须有另一个函数在新的正文中调用它。我解释一下:有一个函数update
,用来更新游戏状态;它被传递当前游戏状态,一个单独的主体
,并返回更新后的主体
update (Body (BodyGeo (PointPlus xy (xi, yi)) wh) pict) = (Body (BodyGeo (move (PointPlus xy (xi, yi))) wh) pict)
这让我发痒。除了PointPlus
之外,正文中的所有内容都保持不变。有没有办法避免这种完全的手工“重建”?例如:
update body = backInBody $ move $ pointPlus body
当然,不必定义背部。您正在寻找“镜头”。镜片有几种不同的包装;这是对它们的一个很好的总结
我的理解是,对于某些字段b
,数据类型a
上的镜头提供了两种操作:一种是获取b
值的方法,另一种是获取具有不同b
值的新a
。因此,您只需使用镜头来处理深度嵌套的PointPlus
镜头包提供了使用镜头的有用功能,以及自动生成镜头的方法(使用模板Haskell),这可能非常方便
我认为它们对于您的项目是值得研究的,特别是因为由于数据类型的结构,您可能会在其他地方遇到类似的嵌套问题。这太完美了,尤其是在自动生成的情况下!移动功能如何?它是把整个身体
,还是只把它的PointPlus
部分拿出来比较好?@L01man我在我的一篇关于镜头的博客文章中也描述了一个与你非常相似的具体例子。你的逐步解释帮助我完全理解镜头。你不认为Haskell应该默认实现镜头吗?类型是语言的一部分,记录语法与镜头有点冗余,但功能不太强大。