Is there a way to remove duplicate where statements in Haskell?

haskell

Solution

What about making these functions take the tuple as an argument, and then wrapping them with another function that automatically does the boring work of extracting the tuple?

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)

Edit: Reviewing my answer six months later, I note there is some more duplication that could be lifted out: the `move camera` call. So really your functions like `moveForward` can just take a 3-tuple and return a 3-tuple, like so:

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)

This gives less power to `moveForward` and `moveBackward`, of course, since you can't use them to do anything but move. But it nicely distills them down to their essences, and ensures you can't accidentally do something other than move.

Problem

I have the following code in 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 ``` You'll notice that the `moveForward` and `moveBackward` functions have identical `where` statements. Is there a way to remove this duplication? I have numerous functions with the same `where` clauses (read: more than two). I would prefer not to pass it in as another argument - since it will never change. It will always be `cRotation`.

Original source