2

次のことについて最善の方法について質問があります

クラス B があり、B にコンビネータがあり、foo : B -> int とします。

クラス B にメソッドとしてカプセル化されたコンビネータを持たせたいので、型拡張で追加します。

私は後で foo が非常に高価であり、遅延評価で結果をキャッシュしたいことに気付きました

そのため、コンビネーターを関数としてコンストラクターに渡し、コンストラクターで foo = lazy(foo self) を使用してフィールドを初期化することで、システムに巨大なクラッチを追加します。

すなわち

type foo =
    class
        val x : int Lazy

         new (comb) as self = {x=lazy(comb self);}
     end
 let something (x:foo) = 1

 type foo with
      new() = foo(something)

これは明らかに気分が悪い

これを修正するために私が見る2つのオプションは、1、インターフェースを作成し、fooにそのインターフェースを継承させる、2、すべてを静的メソッドにしてから、それらの静的メソッドからコンビネーターを作成することです(クラスにアタッチするのとは逆のようなものです... )

これらはどちらも非常に魅力的ではなく、オプション 3 を見逃したのではないかと思っていました。

ああ、私は let rec を取得できず、これをうまく処理できませんでした。また、上記のステートメントの「何か」は、関数に依存する関数に依存する関数に依存するので、本当にしたくありません( 3 深さ)。

アドバイスをいただければ幸いです

4

2 に答える 2

3

現在のデザインに問題はないと思います。重要な点はFoo、同じファイル(および同じモジュール)で型と型の拡張子を定義すると、F#は定義の2つの部分を1つの.NET型に結合することです。したがって、2つの別々の部分で定義されているという事実は、実装の詳細にすぎません。

コンビネータを使用するコンストラクターを公開したくない場合は、としてマークを付けることができますprivate。いくつかの追加の変更(つまり、暗黙のコンストラクタ構文を使用)とともに、スニペットは次のようになります。

type Foo private (comb) as self =
  let x : Lazy<int> = lazy comb self

let something (x:Foo) = 1

type Foo with
  new() = Foo(something)

別の関数として保持したい場合somethingは、これは優れたソリューションです。F#PowerPackの多くの数値タイプは、このパターンに従います(たとえば、複素数の定義を参照してください) 。

于 2011-04-05T23:39:37.353 に答える
2

私はあなたが何を求めているのかよくわかりませんが、これは役立つかもしれないと思います:

type foo(comb) as self =
    let x = lazy(comb self)
    static member something (x:foo) = 1 
    new() = foo(foo.something)

型はそれ自体の静的メンバーで再帰的になる可能性があるため、これはコードを記述するためのより簡単な方法です。

于 2011-04-05T23:39:34.017 に答える