有没有办法在Haskell中删除重复的where语句?

sda*_*das 3 haskell

我在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)

您会注意到moveForwardmoveBackward函数具有相同的where语句.有没有办法删除这种重复?我有许多具有相同where条款的函数(读取:超过两个).

我宁愿不把它作为另一个论点传递 - 因为它永远不会改变.它永远都是cRotation.

ama*_*loy 7

如何使这些函数将元组作为参数,然后用另一个函数包装它们,自动完成提取元组的无聊工作?

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)

这使更低的功率moveForwardmoveBackward,当然,因为你不能用它们做什么,但招.但它很好地将它们提炼到它们的本质,并确保你不会意外地做一些除了移动之外的事情.