1

I'm trying to divide matrix by its last row (each column by its last element - aka Homogeneous coordinates) and then return submatrix containing everything except that last row. Something like this in Matlab:

normx = bsxfun(@rdivide,A,A(end,:));
output = normx(1:end-1,:);

Since I'm new to F# I'm not quite sure about anything, but I tried this:

let hnorm(A:Matrix<double>) = 
    let partialResult = A |> Matrix.iterCols (fun col -> col/col.[col.Count-1])
    partialResult.Rows(0,3)

but I got the "This expression was expected to have type 'unit' but here has type 'Vector< double >'" error in the lambda expression.

And I don't understand what is wrong since examples like

let result = [2;4;6] |> List.map (fun x -> x * x * x)

work well.

Could someone please explain how this can be done because I think I'm missing some basics or misunderstood them.

Thanks!

Dan
  • 77
  • 7

1 Answers1

4

If you look at the signature of Matrix.iterCols (hover on it in your IDE), you'll see that the argument it takes is a function Vector<'a> -> unit - that is, it's a function that takes a Vector<'a> as argument and returns a unit.

Your function fun col -> col/col.[col.Count-1], on the other hand, actually returns a Vector<_>, because that's the result of division there. Since Vector<_> is not a unit, the compiler complains: "this value was expected to have type 'unit', but here has type Vector<>". This is what the compiler is trying to tell you.

As a matter of F# convention, functions named iter* usually mean "go over this sequence and produce some side-effect for every element", where side-effect might be something like printing to the screen or modifying a memory cell, etc. This is why the argument of iterCols is expected to return unit: its sole purpose is to produce a side-effect, it shouldn't return any useful values.

But what you're trying to do is not to produce a side-effect. What you're trying to do is to create another Matrix, which would have all its columns divided by their last element. This operation of transforming a container by applying some function to each of its elements is traditionally called "map" in functional programming. And lo: there is actually a function Matrix.mapCols, which does exactly what you expect:

let partialResult = A |> Matrix.mapCols (fun idx col -> col/col.[col.Count-1])

Note that the argument of mapCols should take two parameters instead of one: the first is the column index, and the second is the column itself.

Fyodor Soikin
  • 78,590
  • 9
  • 125
  • 172
  • 1
    Thanks! That's it. Additional question, since I'm supposed to write `idx` which I won't use, is there some _omit_ symbol like`~` in Matlab? Maybe smth like `fun _ col -> col/col.[col.Count-1]`? – Dan May 22 '18 at 15:54
  • 2
    Yes, that's exactly the syntax. You can use underscore for variable that you don't care about – Fyodor Soikin May 22 '18 at 18:58