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 T
s, 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
newtype
for at least one of them or, if use(Int,Int)
for several other reasons, then why not making all of themnewtype
s 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)
.
T
being not aNum
ber, and adopting your suggested solution, implies that(T 3) * 3
cannot (probably should not, based on what you write) be made meaningful because at least I have to use another symbol instead of*
. Is this correct? – Inwrap