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は、定義が他のものと競合しないことがわかっている場合、または演算子を小さなスコープ (関数内) でローカルに定義している場合に役立ちます。

カスタム型の場合、演算子を静的メンバーとして定義することをお勧めします。このアプローチのもう 1 つの利点は、型が C# (演算子を含む) から使用できることです。

あなたの例でこれを行うには、型定義を型エイリアス (スタンドアロン型ではないため、独自の静的メンバーを持つことはできません) から、メンバーを持つことができる単一ケースの識別共用体に変更する必要がありましたが、とにかくこれはおそらく良い考えです。

于 2013-10-30T13:27:06.760 に答える