I wrote a mathematical Vector module in Haskell.
So I started out with:
data Vector a = Vector !a !a !a deriving (Eq, Show)
Fine—this lets me use any numerical data type I want. The problem is that I don’t want to be writing Double and Vector Double everywhere for the simple reason that I shouldn’t have to. So I add:
type Scalar = Double
type Vector = Vector Scalar
But of course that second line is wrong, since there are now two declarations of Vector. So what should I change it to? I think to myself, no, I’m going to be writing this all over my code, so I want to leave the type alias simply as Vector. Which means I have to change the data type name. But if I change that, then I feel like I should also change the constructor, which makes everything more confusing. But if it feels awkward making the constructor have the same name as the type alias this way.
Right now I have this:
type Scalar = Double
type Vector = VectorT Scalar
data VectorT a = Vector !a !a !a deriving (Eq, Show)
I picked T arbitrarily (I guess it stands for “type”) but I’m not so sure about this. Normally when I document functions I would say -- Calculate the magnitude of a Vector, but with VectorT I feel like I should really be using that type name. So I resort to just referring to them as vectors (not capitalized)—except then I feel like I have to apply this convention to every comment for every data type.
Has anyone been in a similar situation? Can anyone think of a more elegant solution in this case?
One solution to your particular problem would be to have the data type in a different module from the type synonym. That is, have a
Math.Vectormodule which contains the data declaration and some generic functions (that is, functions working for all numeric types). Then, when you actually useVector Doublein your code a lot, just create the type synonym using a qualified import:I think this makes sense from a code organization standpoint. Particularly, if you’ve defined your
Vectortype to work on all numeric types, I expect the functions in that module to also work on all numeric types. The fact that you useVector Doublea lot in some other part of the code should not affect the module whereVectoris actually defined. After all, it’s completely reasonable to imagine usingVector Inta lot in yet another part of your program.As an aside, I’m not sure calling it
Vectoris the best idea. A vector does not necessarily have to have three dimensions, so I would call your data type something likeVector3D. This is actually the name used in some other APIs (like the Java 3D API), so it’s probably a good choice.