2012-11-09 10 views

答えて

18

答えは、どの問題を解決しようとしているかによって異なります。 F#にはタイプクラスとGADTがないため、直接マッピングはありません。しかし、F#が、あなたが一般的にGADTsと型クラスを使用してHaskellで解決する問題を解決するために使用するさまざまなメカニズムを持っています

  • オブジェクトの構造を表すとは異なる動作を持つ新しい具象実装を追加できるようにしたい場合は、標準のOOとインタフェースを使用することができます。あなたは、一般的な数値コードを書きたい場合は

  • 、あなたはおそらく技術的にクラスを入力するための最も近いメカニズムである、静的メンバの制約(here is an example)を使用することができます。

  • より高度な汎用コード(汎用プリンタまたはパーサーのような)を作成する場合は、powerful F# runtime reflectionの機能を使用することがよくあります。

  • (コードで必要なさまざまなサブ操作を実行する)一連の関数でコードをパラメータ化する必要がある場合は、@ padが示すようにインターフェイスの実装を渡すことができます。

emulate Haskell type classes in F#への道がありますが、F#プログラミングスタイルは、いくつかの方法でHaskellのスタイルと異なっているため、これは、通常、慣用F#ソリューションではありません。これをかなり標準的に使用するのは、オーバーロードされた演算子を定義することです(this SO answer参照)。

メタレベルでは、他の言語のフィーチャXと同等のものを尋ねると、Xがある言語で問題A、B、Cを解決するために使用される可能性があるため、同じ問題を解決するためのさまざまな機能を提供します(または、問題の一部がまったく存在しない可能性があります)。

8

F#では、これらの目的で、よくinterfacesinheritanceを使用します。

例ために、ここでは簡単なインターフェースを使用して型クラスとobject expressionsです:

/// Typeclass 
type MathOps<'T> = 
    abstract member Add : 'T -> 'T -> 'T 
    abstract member Mul : 'T -> 'T -> 'T 

/// An instance for int 
let mathInt = 
    { new MathOps<int> with 
     member __.Add x y = x + y 
     member __.Mul x y = x * y } 

/// An instance for float 
let mathFloat = 
    { new MathOps<float> with 
     member __.Add x y = x + y 
     member __.Mul x y = x * y } 

let XtimesYplusZ (ops: MathOps<'T>) x y z = 
    ops.Add (ops.Mul x y) z 

printfn "%d" (XtimesYplusZ mathInt 3 4 1) 
printfn "%f" (XtimesYplusZ mathFloat 3.0 4.0 1.0) 

は、それは非常に美しく見えるかもしれないが、それはそれを行うにはF#-ish方法です。操作の辞書を使用するHaskellのようなソリューションの場合は、this nice answerをご覧ください。

+1

数値コードの場合、 'let inline XtimesYplusZ x y z =(x * y)+ z'と' XtimesYplusZ 3 4 1'と 'XtimesYplusZ 3.0 4.0 1.0'が動作するので、誤解を招く可能性があります。もちろん、別のシナリオでは、デモンストレーションしているスタイルに基づくコードは、この種のパラメータ化を操作でモデル化する良い方法になります。私はそれが、Haskellの型クラスによって解決されたさまざまな問題に対して、異なるアプローチがあると言っていることを意味します。 –

+1

はい、私は良い例を見つけるのに苦労しました。私が実証したいのはコーディングスタイルだけです。それは数値コードに関するものではありません。 – pad

関連する問題