2012-11-09 61 views

回答

18

答案取決於你想解決什麼問題。 F#沒有類型類和GADT,所以沒有直接映射。然而,F#有,你會用它來解決使用GADTs和類型類,您通常解決的問題在Haskell的各種機制:

  • 如果你想表示對象的結構,並能夠與不同的行爲增加新的具體實現,那麼你可以經常使用標準的OO和接口。

  • 如果你想編寫通用的數字代碼,您可以使用靜態成員的約束(here is an example),這可能是技術上鍵入類最接近的機制。

  • 如果您想編寫更高級的通用代碼(如通用打印機或解析器),那麼您通常可以使用powerful F# runtime reflection功能。

  • 如果您需要通過一組函數(執行代碼所需的各種子操作)來參數化代碼,那麼您可以將一個接口的實現作爲@pad顯示來傳遞。

還有一個辦法emulate Haskell type classes in F#,但是這通常不是一個地道的F#的解決方案,因爲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

相關問題