Garnet
Garnet

Reputation: 107

Finding norm of vector using hmatrix in haskell

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

Answers (2)

Gabriella Gonzalez
Gabriella Gonzalez

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 Doubles 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 Doubles 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

Sarah
Sarah

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

Related Questions