Haskell:函数应该接收"多少"类型?并避免完全"重建"

L01*_*man 10 haskell types function

我有这些数据类型:

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)
Run Code Online (Sandbox Code Playgroud)

它是我游戏中角色,敌人,物体等的基本数据类型(好吧,我现在只有两个矩形作为玩家和地面:p).

当一个键,字符通过改变它来向右,向左或跳跃velocity.移动是通过添加velocitycoords.目前,它的编写如下:

move (PointPlus (x, y) (xi, yi)) = PointPlus (x + xi, y + yi) (xi, yi)
Run Code Online (Sandbox Code Playgroud)

我只是接受了PointPlus我的一部分,Body而不是全部Body,否则它将是:

move (Body (BodyGeo (PointPlus (x, y) (xi, yi)) wh) col) = (Body (BodyGeo (PointPlus (x + xi, y + yi) (xi, yi)) wh) col)
Run Code Online (Sandbox Code Playgroud)

第一版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)
Run Code Online (Sandbox Code Playgroud)

这让我感到痒痒.Body除了之外,一切都保持不变PointPlus.有没有办法避免手工完成"重建"?像:

update body = backInBody $ move $ pointPlus body
Run Code Online (Sandbox Code Playgroud)

backInBody当然,无需定义.

Tik*_*vis 14

你正在寻找"镜头".镜片有几种不同的包装; 是对它们的一个很好的总结.

我的理解是,a某个字段的数据类型上的镜头b提供了两种操作:获取值的b方法和获取a具有不同值的新方法b.因此,您只需使用镜头即可深度嵌套PointPlus.

镜头包提供了与镜头一起使用的有用功能以及自动生成镜头的方法(使用模板Haskell),这可能非常方便.

我认为他们值得研究您的项目,特别是因为您的数据类型结构可能会遇到类似的嵌套问题.

  • @ L01man我还在我的镜头博客文章中描述了一个与你非常相似的具体例子[这里](http://www.haskellforall.com/2012/01/haskell-for-mainstream-programmers_28.html) (3认同)