让每个枚举元素与唯一的Vector值相关联

时间:2014-06-23 00:35:11

标签: haskell types enums enumeration

我考虑过制作一个Direction数据类型,并且我想让每个元素与3d Vector相关联,指示方向的x,y和z值。例如,Up的值为0 1 0.这样做的好方法是什么?

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

以下是最好的方式吗?:

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

1 个答案:

答案 0 :(得分:1)

根据n.m.的建议,您可以使用数组。

{-# 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]

Direction索引到数组将为您提供Point3

>>> dir ! Above
Point3 0 0 1

这将比一个函数具有轻微的性能优势,因为你将拥有预先构造的Point3的永久缓存,因此不会导致任何分配。

另一个好处是代码非常整洁!

缺点是它需要Direction为Ord,Eq和Ix。