2016-11-24 2 views
3

F#でVectorおよびMatrixクラスを実装したいとします。言語は循環的な依存関係を許さないので、VectorクラスとMatrixクラスの両方を参照することはできません。さらに、どちらのクラスも他のクラスに依存しないという選択をしているとしましょう(たとえば、VectorはMatrixに依存しますが、逆の場合は異なります)。中置演算子を実装する際に循環依存関係を回避する方法

ここでは、MatrixインスタンスとVectorインスタンスの右乗算を実装したいと考えています。つまり、a * b(aは行列、bはベクトル)です。最初の考え方は、op_Multiplyを例えばMatrixクラスの静的メンバメソッドとして宣言することです。 C#では、このようなシグネチャを持つ静的メソッドを持つことを意味します。

public static Vector operator *(Matrix matrix, Vector vector); 

Matrixクラスただし、この操作はVectorクラスとMatrixクラスの両方に依存するため、MatrixクラスとVectorクラスのどちらでも宣言することはできません。これらは相互に依存することができないためです。

次の思考はの効果に何かをF#で、拡張メソッドのいくつかの並べ替えとしてそれを宣言するかもしれない

[<Extension>] 
static member (*) (matrix : IMatrix, vector : IVector) = 
    ... 

はしかし、これは単に

a.op_Multiply(b) 
ような何かを書くために私を可能に

ありません

a * b 

ここでの問題は、「operator extアンサンブルの方法 "。 MatrixとVectorが互いに依存するのを避け、 "a * b"のようなものを書くこともできるように、乗法を定義するにはどうすればよいですか?

module Foo = 
    type Bar = Bar of string 

module Ploeh = 
    type Fnaah = Fnaah of string 

[<AutoOpen>] 
module Operators = 
    let (+) (Foo.Bar b) (Ploeh.Fnaah f) = b + f 

open Foo 
open Ploeh 

let sum = (Bar "sgryt") + (Fnaah "ler") 

これは、少なくとも、FSIに期待される出力を生成します:

> let sum = (Bar "sgryt") + (Fnaah "ler");;  
val sum : string = "sgrytler" 

それはないです

+2

最初に、F#は円d小さな文脈における独立性。あなたが 'Vector'と' Matrix'を互いを参照するように完全にすることができます。第2に、以前に定義された型の演算子を定義するには、それをクラスメソッドではなく自立した関数にします。 –

答えて

4

は、私はあなたが[<AutoOpen>]属性を持つモジュールにlet結合型の関数としての演算子を書くことができると思います私はしばしば何かをするので、実際にはあまり理想的ではないコーナーケースがあるかどうかは言えません...

関連する問題