2012-11-09 26 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

相关问题