This is a common misunderstanding of people new to Haskell's style of typeclass based overloading, especially those who are used to the subclass-based overloading used in popular OO languages.
The subtraction operator has type Num a => a -> a -> a
; so it takes two arguments of any type that is in the type class Num
. It seems like what is happening when you do m - 3
is that the subtraction operator is accepting a Matrix Double
on the left and some simple numeric type on the right. But that is actually incorrect.
When a type signature like Num a => a -> a -> a
uses the same type variable multiple times, you can pick any type you like (subject to the contstraints before the =>
: Num a
in this case) to use for a
but it has to be the exact same type everywhere that a
appears. Matrix Double -> Double -> ???
is not a valid instantiation of the type Num a => a -> a -> a
(and if it were, how would you know what it returned?).
The reason m - 3
works is that because both arguments have to be the same type, and m
is definitely of type Matrix Double
, the compiler sees that 3
must also be of type Matrix Double
. So instead of using the 3
appearing in the source text to build a Double
(or Integer
, or one of many other numeric types), it uses the source text 3
to build a Matrix Double
. Effectively the type inference has changed the way the compiler reads the source code text 3
.
But if you use m' = m - (3::Double)
then you're not letting it just figure out what type 3
must have to make the use of the subtraction operator valid, you're telling it that this 3
is specifically a Double
. There's no way both facts to be true (your :: Double
assertion and the requirement that the subtraction operator gets two arguments of the same type), so you get a type error.
Matrix Double
is another specific instance of Num, but subtraction requires both arguments to be of the same type. – ErikR3
actually has the typeMatrix Double
in your example. Numbers are overloaded in Haskell. – Alec