I was a bit surprised when the following code wouldn’t compile:
-- Code 1
import Complex
type Velocity = Complex Double
type Force = Complex Double
type FrictionCoeff = Double
frictionForce :: FrictionCoeff -> Velocity -> Force
frictionForce mu vel = mu * vel
The error says
Couldn't match expected type `Complex Double'
with actual type `Double'
Expected type: Force
Actual type: FrictionCoeff
In the first argument of `(*)', namely `mu'
In the expression: mu * vel
So, in short
-- Code 2
let z = 1 :+ 2
z * 3 -- Goes fine.
z * 2.5 -- Goes fine.
z * (2.5 :: Double) -- Explodes.
Complex defines (*) as
instance (RealFloat a) => Num (Complex a) where
(x:+y) * (x':+y') = (x*x'-y*y') :+ (x*y'+y*x')
Why can 3 (Num a => a) and 2.5 (Fractional a => a) be pattern-matched against (x:+y), but a Double cannot ?
First off, the type of the multiplication operator is
which means that you can only multiply numbers of the same type, which is why multiplying a
Complex Doubleby aDoublewon’t work.So why does multiplying a complex number with a decimal literal work?
It works because numeric literals are polymorphic in Haskell, so when you type an integer literal like
42, it really meansfromInteger 42. Similarly, decimal literals like2.3becomesfromRational (23 % 10). If you examine the types of those functions,this means that integer literals can be any numeric type, while decimal literals can be any fractional type. Complex numbers are both, which is why both
z * 3andz * 2.5work.When you aren’t dealing with literals, you have to convert. For example, your original function can be fixed by writing:
Finding the appropriate conversion function is easy using Hoogle, since you can search for functions by type. In this case, searching for
Double -> Complex Doublegives(:+)as the top result.