使用管道

时间:2018-05-22 13:40:35

标签: f# linear-algebra mathnet

我试图将矩阵除以其最后一行(每列由其最后一个元素 - 也称为Homogeneous坐标),然后返回包含除最后一行之外的所有内容的子矩阵。 在Matlab中有类似的东西:

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

由于我是F#的新手,我不太确定任何事情,但我试过了:

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

但是我得到了&#34; 这个表达式应该有类型&#39; unit&#39;但这里有类型&#39; Vector&lt;双&gt;&#39; &#34; lambda表达式中的错误。

我不明白自

等例子以来出了什么问题
let result = [2;4;6] |> List.map (fun x -> x * x * x)

运作良好。

有人可以解释一下如何做到这一点,因为我认为我错过了一些基础知识或误解了它们。

谢谢!

1 个答案:

答案 0 :(得分:4)

如果你看一下Matrix.iterCols的签名(在你的IDE中悬停它),你会发现它所采用的参数是一个函数Vector<'a> -> unit - 也就是说,它是&#39 ;一个以Vector<'a>为参数并返回unit的函数。

另一方面,您的函数fun col -> col/col.[col.Count-1]实际上会返回Vector<_>,因为那是在那里划分的结果。由于Vector<_>不是unit,编译器会抱怨:&#34;此值应该具有类型&#39; unit&#39;,但这里的类型为Vector&lt;&gt; &#34; 。这就是编译器试图告诉你的。

作为F#惯例的问题,名为iter*的函数通常意味着&#34;重复此序列并为每个元素产生一些副作用&#34; ,其中 - 效果可能类似于打印到屏幕或修改存储单元等。这就是为什么iterCols的参数应该返回unit:它的唯一目的是产生副作用,它不应该返回任何有用的值。

但是你要做的是而不是来产生副作用。你要做的是创建另一个Matrix,它的所有列都被它们的最后一个元素分开。通过将一些函数应用于其每个元素来转换容器的这种操作传统上称为&#34; map&#34;在函数式编程中。并且:实际上有一个函数Matrix.mapCols,它完全符合您的期望:

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

请注意mapCols的参数应该采用两个参数而不是一个:第一个是列索引,第二个是列本身。