Haskell data type alias naming
-
19-06-2021 - |
Question
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?
La solution
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.Vector
module which contains the data declaration and some generic functions (that is, functions working for all numeric types). Then, when you actually use Vector Double
in your code a lot, just create the type synonym using a qualified import:
import qualified Math.Vector as MV
type Scalar = Double
type Vector = MV.Vector Scalar
I think this makes sense from a code organization standpoint. Particularly, if you've defined your Vector
type to work on all numeric types, I expect the functions in that module to also work on all numeric types. The fact that you use Vector Double
a lot in some other part of the code should not affect the module where Vector
is actually defined. After all, it's completely reasonable to imagine using Vector Int
a lot in yet another part of your program.
As an aside, I'm not sure calling it Vector
is the best idea. A vector does not necessarily have to have three dimensions, so I would call your data type something like Vector3D
. This is actually the name used in some other APIs (like the Java 3D API), so it's probably a good choice.
Autres conseils
Is there any specific reason to not just do
data Vector = Vector !Double !Double !Double deriving (Eq, Show)
That seems like the simplest idea to me...