Suppose I have a custom type wrapping an existing type,
newtype T = T Int deriving Show
and suppose I want to be able to add up Ts, and that adding them up should result in adding the wrapped values up; I would do this via
instance Num T where
(T t1) + (T t2) = T (t1 + t2)
-- all other Num's methods = undefined
I think we are good so far. Please, tell me if there are major concerns up to this point.
Now let's suppose that I want to be able to multiply a T by an Int and that the result should be a T whose wrapping value is the former multiplied by the int; I would go for something like this:
instance Num T where
(T t1) + (T t2) = T (t1 + t2)
(T t) * k = T (t * k)
-- all other Num's methods = undefined
which obviously doesn't work because class Num declares (*) :: a -> a -> a, thus requiring the two operands (and the result) to be all of the same type.
Even defining (*) as a free function poses a similar problem (i.e. (*) exists already in Prelude).
How could I deal with this?
As for the why of this question, I can device the following
- in my program I want to use
(Int,Int)for 2D vectors in a cartesian plane, - but I also use
(Int,Int)for another unrelated thing, - therefore I have to disambiguate between the two, by using a
newtypefor at least one of them or, if use(Int,Int)for several other reasons, then why not making all of themnewtypes wrapping(Int,Int)? - since
newtype Vec2D = Vec2D (Int,Int)represents a vector in the plain, it makes sense to be able to doVec2D (2,3) * 4 == Vec2D (8,12).