我开始为笛卡尔积和矩阵乘法定义我自己的算子。
将矩阵和向量别名为列表:
type Matrix = float list list
type Vector = float list
我可以写下我自己的初始化代码(并通过写作获得笛卡尔产品)
let inline (*) X Y =
X |> List.collect (fun x -> Y |> List.map (fun y -> (x, y)))
let createVector size f =
[0..size - 1] |> List.map (fun i -> f i)
let createMatrix rows columns f =
[0..rows - 1] * [0..columns - 1] |> List.map (fun i j -> f i j)
到目前为止一切顺利。问题是我对*
的定义消除了正常定义,即使我的版本仅为列表定义,但没有自己的乘法运算符。
文档http://msdn.microsoft.com/en-us/library/vstudio/dd233204.aspx指出“新定义的运算符优先于内置运算符”。但是,我没想到所有的数字化身都被消灭了 - 当然静态打字会照顾到这个吗?
我知道可以定义一个尊重类型的全局运算符,因为MathNet Numerics使用*
进行矩阵乘法。我还想走这条路,这需要打字系统优先考虑矩阵乘法优先于Matrix
类型(它们本身就是列表)的笛卡尔乘积。
有人知道如何在F#中执行此操作吗?
答案 0 :(得分:13)
这是(非惯用的)解决方案:
type Mult = Mult with
static member inline ($) (Mult, v1: 'a list) = fun (v2: 'b list) ->
v1 |> List.collect (fun x -> v2 |> List.map (fun y -> (x, y))) : list<'a * 'b>
static member inline ($) (Mult, v1:'a ) = fun (v2:'a) -> v1 * v2 :'a
let inline (*) v1 v2 = (Mult $ v1) v2
答案 1 :(得分:10)
惯用解决方案是将Matrix
定义为新类型,并将运算符添加为静态成员:
type Matrix =
| MatrixData of float list list
static member (*) (MatrixData m1, MatrixData m2) = (...)
使用let
定义的运算符在您知道定义与其他任何内容不冲突时,或者在小范围内(在函数内)本地定义运算符时非常有用。
对于自定义类型,最好将运算符定义为静态成员。这种方法的另一个好处是您的类型可以从C#(包括运算符)中使用。
要在您的示例中执行此操作,我必须将类型定义从类型别名(不是独立类型,因此它不能拥有自己的静态成员)更改为单个案例区分联合,它可以具有成员 - 但无论如何这可能是一个好主意。