Reputation: 107
I just started learning Haskell and am having trouble with using the hmatrix library. I want to write some simple code to compute the eigenvalue using the power iteration method. I start with:
c = fromList [4.0, 4.0, 4.0, 4.0]::Vector Double
n = norm2 c
Which creates a vector c and finds the 2-norm of the vector.
Multiplication with c
:
c * 2 (Works)
c * 0.5 (Works)
c * pi (Works)
c * n (Error)
I checked that:
>:t pi
pi :: Floating a => a
>:t n
n :: Double
The problem is with the types but I do not know how to get around it.
Would I need to define my own (/)
function in this case?
Update: The error I obtain from ghci:
Couldn't match expected type `Vector Double'
with actual type `Double'
In the second argument of `(*)', namely `n'
In the expression: c * n
In an equation for `it': it = c * n
Upvotes: 2
Views: 437
Reputation: 35099
(*)
assumes that both of its arguments have the same type:
(*) :: (Num a) => a -> a -> a
The reason that your first three multiplications worked was because in all three cases the right argument successfully type-checked as a Vector Double
!
To see why, let's ask ghci
what the types of those three arguments are:
> :t 2
2 :: Num a => a
> :t 0.5
0.5 :: Fractional a => a
> :t pi
pi :: Floating a => a
All three of those are valid Vector Double
s because hmatrix
provides the following three instances:
instance Num (Vector Double) where ...
instance Fractional (Vector Double) where ...
instance Floating (Vector Double) where ...
In other words, Haskell will transform 2
, 0.5
, and pi
into Vector Double
s automatically, thanks to those instances.
This explains why your last example does not type check. n
has type Double
, which means that there is no chance it can ever type-check also as a Vector Double
.
Upvotes: 2
Reputation: 6696
You're doing the right thing by checking the types. If we're a bit more explicit, we can see what is going on.
Prelude Numeric.LinearAlgebra> :t let a = 2; b = c * a in a
let a = 2; b = c * a in a :: Vector Double
The problem is that the type of norm2 c
is Double
and thus cannot be made into a Vector Double
Let's see the value of that polymorphic 2
from earlier.
Prelude Numeric.LinearAlgebra> let a = 2; b = c * a in a
fromList [2.0]
So instead, n = fromList [norm2 c]
Edit: The very same library exposes functions scalar
and scale
which you should look into.
Upvotes: 2