我在Haskell中有以下代码:
move :: Camera -> (Double, Double, Double) -> Camera
move camera (xt, yt, zt) = camera { cPosition = (x + xt, y + yt, z + zt) }
where (x, y, z) = cPosition camera
moveForward :: Camera -> Camera
moveForward camera = move camera (-1 * sin ya, 0, -1 * cos ya)
where (_, ya, _) = cRotation camera
moveBackward :: Camera -> Camera
moveBackward camera = move camera (sin ya, 0, cos ya)
where (_, ya, _) = cRotation camera
Run Code Online (Sandbox Code Playgroud)
您会注意到moveForward和moveBackward函数具有相同的where语句.有没有办法删除这种重复?我有许多具有相同where条款的函数(读取:超过两个).
我宁愿不把它作为另一个论点传递 - 因为它永远不会改变.它永远都是cRotation.
如何使这些函数将元组作为参数,然后用另一个函数包装它们,自动完成提取元组的无聊工作?
rotated :: ((Double, Double, Double) -> Camera -> a) -> Camera -> a
rotated f camera = f (cPosition camera) camera
moveForward :: Camera -> Camera
moveForward = rotated moveForward'
where moveForward' (_, ya, _) camera = move camera (-1 * sin ya, 0, -1 * cos ya)
moveBackward :: Camera -> Camera
moveBackward = rotated moveBackward'
where moveBackward' (_, ya, _) camera = move camera (sin ya, 0, cos ya)
Run Code Online (Sandbox Code Playgroud)
编辑:六个月后回顾我的答案,我注意到还有一些可以解除的重复:move camera电话.所以你的功能真的moveForward可以只需要一个3元组并返回一个3元组,就像这样:
moveRotated :: ((Double, Double, Double) -> (Double, Double, Double)) -> Camera -> Camera
moveRotated f camera = move camera . f $ cPosition camera
moveForward :: Camera -> Camera
moveForward = moveRotated forward
where forward (_, ya, _) = (- sin ya, 0, - cos ya)
moveBackward :: Camera -> Camera
moveBackward = moveRotated backward
where backward (_, ya, _) = (sin ya, 0, cos ya)
Run Code Online (Sandbox Code Playgroud)
这使更低的功率moveForward和moveBackward,当然,因为你不能用它们做什么,但招.但它很好地将它们提炼到它们的本质,并确保你不会意外地做一些除了移动之外的事情.