16

我开始为笛卡尔积和矩阵乘法定义自己的运算符。

使用别名为列表的矩阵和向量:

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# 中做到这一点?

4

2 回答 2

15

这是(非惯用的)解决方案:

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
于 2013-10-30T15:42:54.787 回答
12

惯用的解决方案是定义Matrix为新类型并将运算符添加为静态成员:

type Matrix = 
  | MatrixData of float list list
  static member (*) (MatrixData m1, MatrixData m2) = (...)

let当您知道定义不与其他任何内容冲突时,或者当您在小范围内(在函数内)本地定义运算符时,使用定义的运算符很有用。

对于自定义类型,最好将运算符定义为静态成员。这种方法的另一个好处是您的类型可以在 C#(包括运算符)中使用。

要在您的示例中执行此操作,我必须将类型定义从类型别名(它不是独立类型,因此它不能有自己的静态成员)更改为可以有成员的单例区分联合 - 但是无论如何,这可能是个好主意。

于 2013-10-30T13:27:06.760 回答