Having each enum element associated with a unique Vector value

I thought about making a Direction data type and I'd like to have each element associated with a 3d Vector indicating the x, y and z value of the direction. Up, for instance, would have the value 0 1 0. What is a good way to do this?

data Direction = None | Up | Right | Down | Left | Above | Below deriving (Enum)

Is doing as below really the best way?:

direction :: Direction -> Point3
direction Up               = Point3 0    1    0
direction GameEngine.Right = Point3 1    0    0
direction Down             = Point3 0    (-1) 0
direction GameEngine.Left  = Point3 (-1) 0    0
direction Above            = Point3 0    0    1
direction Below            = Point3 0    0    (-1)
direction None             = Point3 0    0    0

Upvotes: 1

Views: 200

Answers (1)

Thomas
Thomas

Reputation: 11888

As suggested by n.m., you can use an Array.

{-# LANGUAGE NoImplicitPrelude #-}
import Data.Array
import Prelude hiding (Left, Right, abs)

data Direction = None | Above | Below | Up | Down | Right | Left deriving (Enum, Ord, Eq, Ix)

-- helper function for finding absolute value of Point3
abs (Point3 x y z) = sqrt $ fromIntegral $ x^2 + y^2 + z^2

-- written long way using do-notation
dir :: Array Direction Point3
dir = listArray (None, Left) states
  where
    moves = [0, 1, -1]
    states :: [Point3]
    states = do
      x <- moves
      y <- moves
      z <- moves
      let point = Point3 x y z
      guard $ abs point <= 1
      return point

-- written short way using list-comprehension
dir :: Array Direction Point3
dir = listArray (None,Left) [p |
    x <- m, y <- m, z <- m,
    let p = Point3 x y z,
    abs p <= 1
  ] where m = [0, 1, -1]

Indexing into the array by Direction will give you a Point3.

>>> dir ! Above
Point3 0 0 1

This will give you a slight performance advantage over a function because you will have permanent cache of pre-constructed Point3s and hence, will not cause any allocation.

The other bonus is that the code is pretty neat!

The disadvantage is that it requires Direction to be Ord, Eq and Ix.

Upvotes: 1

Related Questions