Search code examples
haskelltypesenumsanonymous-typesalgebraic-data-types

Type with two enum fields in Haskell


I have a type that represents a direction, it has an axis and an orientation:

data Dir = DirX | DirY | DirZ | DirW deriving (Show, Eq)
data Sign = Pos | Neg deriving (Show, Eq)
newtype Direction = Direction (Dir, Sign) deriving (Show, Eq)

And that looks kinda overcomplicated. I don't need Sign and Dir to be distinct types, I just want to pattern match things to their constructors. So is there any nicer way to define such kind of types?

So what I want to do is some kind of

data Direction = Direction (DirX | DirY | DirZ | DirW) (Pos | Neg) deriving (Show, Eq)

Because I do things like \(Direction _ s) -> if s == Pos then ... else ..., but I never use Dir or Sign outside of the Direction

I suppose I'm not the first one to ask this, but I really can't figure out how to google this question.


Solution

  • Nope, there's no nicer way.

    ...then again, personally, I find this way perfectly nice already. So perhaps it is not such a terrible burden to bear.

    Of course, there are ways to define completely different types that might still be of interest to you. For example, I have used a direction type along these lines in the past to good effect:

    data Direction = Direction { x, y, z, w :: Int }
    aboutFace (Direction x y z w) = Direction (-x) (-y) (-z) (-w)
    -- e is a traditional name from linear algebra for an axis-aligned unit vector
    ex = Direction 1 0 0 0
    ey = Direction 0 1 0 0
    ez = Direction 0 0 1 0
    ew = Direction 0 0 0 1