3

FsUnit を使用して F# コードをテストし始めました。これにより、F# スタイルでアサーションを表現できます。たとえば、次のようになります。

[<Test>]
member this.``Portugal voted for 23 countries in 2001 Eurovision contest``() =
    this.totalVotes 
    |> getYearVotesFromCountry "Portugal" 2001
    |> Seq.length
    |> should equal 23

FsUnit から取得した「23 に等しい」ことに注意してください。FsUnit がそれを定義する方法は次のとおりです。

let equal x = new EqualConstraint(x)

浮動小数点数では、それほど単純ではありません。Within メソッドで EqualConstraint を使用する必要があります。自然に C# に適合します。

Assert.That(result).Is.EqualTo(1).Within(0.05);

もちろん、F# で書けるようになりたいです:

result |> should equal 1 within 0.05

しかし、それはうまくいきません。私は新しい関数を定義することになりました:

let almostEqual x = (new EqualConstraint(x)).Within(0.01)

または、精度をパラメータ化したい場合は、2 番目の引数として指定できます。

let equalWithin x y = (new EqualConstraint(x)).Within(y)

しかし、それらのどれもきれいではありません。「with」関数を F# のより自然な方法で定義して、equal と一緒に使用できるようにしたいと考えています。F# はメソッドのオーバーロードをサポートしていないので、"equal" を単独で、または "within" と組み合わせて使用​​できるように定義することはできないようです。

何か案は?

4

2 に答える 2

12

これは興味深い問題です。within 0.05の既存の定義should equalに何らかの方法で追加できるとは思いません。これを行うには、関数にパラメーターを追加する必要がshouldありますが、ライブラリには固定数のパラメーターが必要です。

これを F# でエレガントに記述する 1 つの方法は、カスタム operator を作成することです+/-。まだ括弧を使用する必要があることに注意してください。

0.9 |> should equal (1.0 +/- 0.5)

演算子は、関数で明示的に処理する必要がある特別な型の値を構築するだけequalです。実装は次のとおりです。

type Range = Within of float * float
let (+/-) (a:float) b = Within(a, b)

let equal x = 
  match box x with 
  | :? Range as r ->
      let (Within(x, within)) = r
      (new EqualConstraint(x)).Within(within)
  | _ ->
    new EqualConstraint(x)
于 2010-07-08T16:27:08.530 に答える
0

用語に関する注意: F# はメソッドのオーバーロードをサポートしています。let バインド関数(モジュールで定義された「フリー」関数) のオーバーロードはサポートされていません。

たとえばshould.equal、ドットで作成できます。これは、オブジェクトequalのメソッドであり、オーバーロードできます。shouldカリー化された引数をオーバーロードできないため、それでも役に立ちません。うーん。

わかりました、提供できるものはあまりありません。個人的には、ライブラリ内のこの種のシンタックス シュガーは好きではありません。

于 2010-07-08T16:20:31.040 に答える