与F#中的Haskell GADT和类型类最接近的是什么?

时间:2012-11-09 15:29:38

标签: f# typeclass gadt

F#是带有OOP的ML。与Haskell广义代数数据类型和类型类最接近的是什么?

2 个答案:

答案 0 :(得分:18)

答案取决于您要解决的问题。 F#没有类型类和GADT,因此没有直接映射。但是,F#有各种机制可用于解决通常使用GADT和类型类在Haskell中解决的问题:

  • 如果您想表示对象结构并能够添加具有不同行为的新具体实现,那么您通常可以使用标准OO和接口。

  • 如果要编写通用数字代码,可以使用静态成员约束(here is an example),这可能是技术上最接近类型的机制。

  • 如果您想编写更高级的通用代码(如通用打印机或解析器),那么您通常可以使用powerful F# runtime reflection功能。

  • 如果您需要通过一组函数(执行代码所需的各种子操作)来参数化代码,那么您可以在@pad显示时传递接口的实现。

还有一种方法emulate Haskell type classes in F#,但这通常不是惯用的F#解决方案,因为F#编程风格在很多方面与Haskell风格不同。一个相当标准的用途是定义重载运算符(参见this SO answer)。

在元级别,询问另一种语言中的特征X的等价物通常会导致讨论混乱,因为X可能用于解决一种语言中的问题A,B,C而另一种语言可以提供不同的功能来解决相同的问题(或者根本不存在某些问题)。

答案 1 :(得分:7)

在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# - 这样做的方式。对于使用操作字典的更类似Haskell的解决方案,您可以查看this nice answer