Reputation: 26374
data Ray = Ray Vector Vector
or
type Ray = (Vector, Vector)
Which is preferred in idiomatic haskell? Why should I use one over the other?
I don't care about performance.
It seems to make little difference with functions, e.g.:
trace :: Ray -> …
trace (Ray x d) = …
-- OR
trace (x, d) = …
Upvotes: 16
Views: 1595
Reputation: 54584
A fourth alternative I found quite convenient are records:
data Ray = Ray { from, to :: Vector }
They have basically all the features of "normal" ADTs, but with some additional syntactical sugar. Especially they make it easier to get partially modified copies of a value. It's true that records are too limited in some situations, but then you can go further with "improved versions" like fclabels.
Upvotes: 3
Reputation: 122439
You might also consider a third option that is kind of a combination of the two: newtype
newtype Ray = Ray (Vector, Vector)
Algebraic datatypes, in my opinion, are used in situations when you have multiple alternatives, or in cases when you need the type to be recursive, containing itself. But it might be overkill for something like this.
Don Stewart pointed out that making a type synonym to tuple is the same as using that tuple type directly; type synonyms have no identity of their own. So the type checker would not be able to distinguish between your type and a tuple, and so it cannot check that you're using the type where you want. Also, it would have the exact same instances as a tuple.
A newtype
allows you to use the same underlying type as the tuple; but it's a separate type to the type checker, with separate instances.
Upvotes: 8
Reputation: 137947
The data
version is preferred as it more clearly indicates the intent of the programmer — by creating a new type, you are pointing out to all that this is not merely a tuple, but a meaningful semantic entity, a Ray
.
That then makes it possible to lean on the type system further, with custom instances for Ray
, and optimizations not possible in tuples.
Upvotes: 12