我有一个数组P,它代表一个矩阵,作为一个行向量数组(这种表示对我来说更方便),我想提取该数组的列向量j。我的第一关是:
let column (M: float[][]) (j: int) =
Array.map(fun v -> v.[j]) M
这无法编译,告诉我v。[j]在不确定类型的对象上使用operator expr。[idx]。这对我来说很困惑,因为将鼠标悬停在v上会将v识别为float [],我相信它是一个行向量。
此外,以下代码有效:
let column (M: float[][]) (j: int) =
Array.map(fun v -> v) M
|> Array.map (fun v -> v.[j])
我无法理解第二个例子与第一个例子的不同之处。第二个示例中的第一个映射看起来是多余的:我将数组映射到自身,但这似乎解决了类型确定问题。
任何有助于了解我做错了什么或不看的内容都会非常感激!
答案 0 :(得分:5)
问题是F#类型推断严格从左到右,以便编译器看到
let column (M: float[][]) (j: int) =
Array.map(fun v -> v.[j])
此时,它对v
一无所知,因此会抛出错误。这就是前向管道运算符|>
如此常见的原因 - 将代码重写为
let column (M: float[][]) (j: int) =
M |> Array.map(fun v -> v.[j])
很好。这也是你的第二个例子工作的原因
答案 1 :(得分:3)
由于类型检查器从左向右工作,因此v
的类型未指定,尽管M
的类型稍后可用。因此:
let column (M: float[][]) (j: int) =
M |> Array.map (fun v -> v.[j])
或
let column M (j: int) =
Array.map (fun (v: float []) -> v.[j]) M
作品。
在第二个示例中,任何类型的fun v -> v
都可以。所以数组元素的类型没有问题。 |>
的第二部分按预期工作,并再说明为什么我们应该使用管道运算符。