data Diff = Diff { x :: Float, y :: Float, z :: Float } data Direction = DIR_UP_NORTH_WEST | DIR_UP_SOUTH_WEST | DIR_UP_WEST | DIR_UP_NORTH_EAST | DIR_UP_SOUTH_EAST | DIR_UP_EAST | DIR_UP_NORTH | DIR_UP_SOUTH | DIR_UP | DIR_DOWN_NORTH_WEST | DIR_DOWN_SOUTH_WEST | DIR_DOWN_WEST | DIR_DOWN_NORTH_EAST | DIR_DOWN_SOUTH_EAST | DIR_DOWN_EAST | DIR_DOWN_NORTH | DIR_DOWN_SOUTH | DIR_DOWN | DIR_NORTH_WEST | DIR_SOUTH_WEST | DIR_WEST | DIR_NORTH_EAST | DIR_SOUTH_EAST | DIR_EAST | DIR_NORTH | DIR_SOUTH | DIR_NONE test :: Diff -> Direction test diff = let zero = 0.0 in let c1 = compare zero (x diff) in let c2 = compare zero (y diff) in let c3 = compare zero (z diff) in decide (c1, c2, c3) where decide :: (Ordering, Ordering, Ordering) -> Direction decide (LT, LT, LT) = DIR_UP_NORTH_WEST decide (LT, LT, EQ) = DIR_UP_SOUTH_WEST decide (LT, LT, GT) = DIR_UP_WEST decide (LT, EQ, LT) = DIR_UP_NORTH_EAST decide (LT, EQ, EQ) = DIR_UP_SOUTH_EAST decide (LT, EQ, GT) = DIR_UP_EAST decide (LT, GT, LT) = DIR_UP_NORTH decide (LT, GT, EQ) = DIR_UP_SOUTH decide (LT, GT, GT) = DIR_UP decide (EQ, LT, LT) = DIR_DOWN_NORTH_WEST decide (EQ, LT, EQ) = DIR_DOWN_SOUTH_WEST decide (EQ, LT, GT) = DIR_DOWN_WEST decide (EQ, EQ, LT) = DIR_DOWN_NORTH_EAST decide (EQ, EQ, EQ) = DIR_DOWN_SOUTH_EAST decide (EQ, EQ, GT) = DIR_DOWN_EAST decide (EQ, GT, LT) = DIR_DOWN_NORTH decide (EQ, GT, EQ) = DIR_DOWN_SOUTH decide (EQ, GT, GT) = DIR_DOWN decide (GT, LT, LT) = DIR_NORTH_WEST decide (GT, LT, EQ) = DIR_SOUTH_WEST decide (GT, LT, GT) = DIR_WEST decide (GT, EQ, LT) = DIR_NORTH_EAST decide (GT, EQ, EQ) = DIR_SOUTH_EAST decide (GT, EQ, GT) = DIR_EAST decide (GT, GT, LT) = DIR_NORTH decide (GT, GT, EQ) = DIR_SOUTH decide (GT, GT, GT) = DIR_NONE