【问题标题】:alternative to typeclasses?替代类型类?
【发布时间】:2011-04-09 12:28:44
【问题描述】:

haskell 程序员。使用 F#。 F# 中没有类型类。当我需要类型类时使用什么?

【问题讨论】:

  • 你能举一个具体的例子说明你什么时候“需要类型类”吗?
  • @Jon Harrop:你能举一个具体的例子说明你什么时候“需要”任何语言特性吗?最后,一旦你有了图灵等价性,其他一切都只是语法和便利。类型类是我熟悉的即席多态性最具表现力的方法。你觉得子类型多态和成员重载有用吗?
  • @Jon Harrop:所以我认为你看不到任何用途,比如运算符重载或类型参数约束?
  • @Jon Harrop:好吧,如果您专门研究高性能数值计算,我绝对可以理解为什么它可能与您的日常工作无关,但这是一个相当小的利基市场有独特的要求。另一方面,我希望 @Brian 作为 F# 团队的一员,对如何使用该语言有非常广泛的看法。
  • 字典传递是类型类的一种实现,它不是唯一的方法。 JHC 编译器是(全程序优化)Haskell 编译器的一个示例,它不使用字典传递来实现类型类。

标签: haskell f# functional-programming typeclass


【解决方案1】:

请按照某人的建议查看this

我认为简短的回答是传递操作字典(就像 Haskell 会在幕后一样;实例的见证人)。

或者改变设计,这样你就不需要类型类了。 (这总是让人感到痛苦,因为类型类是有史以来最好的东西,而且很难将它们抛在后面,但在 Haskell 和类型类出现之前,人们仍然设法在没有类型类的情况下进行了 4 年的编程,所以做那些人做的同样的事情.)

您还可以通过inline 静态成员约束获得一些方法,但这很快就会变得丑陋。

这是一个操作字典示例:

// type class
type MathOps<'t> = { add : 't -> 't -> 't; mul: 't -> 't -> 't }  //'

// instance
let mathInt : MathOps<int> = { add = (+); mul = (*) }

// instance
let mathFloat : MathOps<float> = { add = (+); mul = (*) }

// use of typeclass (normally ops would the 'constraint' to the left of 
// the '=>' in Haskell, but now it is an actual parameter)
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)

【讨论】:

  • @Jon Harrop:什么?当然如此。定义类型类和实例与定义类型完全分开。他们甚至不必在同一个模块中。如果没记错的话,Scala 的版本更强大,可以让你有本地范围的定义(但我不了解 Scala,所以我可能会感到困惑)。
  • 似乎还有一个没有提到的问题,不仅仅是缺少类型类。事实上,F#(因为 .NET)不支持更高种类的多态性,这意味着您无法(简单地)实现一些可能在 Haskell 等语言中实现的抽象,即使通过显式字典传递您也无法做到。我真的希望将来在 .NET/F# 中解决这个问题。
  • @Jon Harrop:所以你不喜欢 F# 中的计算表达式,我认为?
  • @Jon 当然是。 Monad 不仅仅用于您知道的副作用。
  • 当然。我经常将replicateM 用于从标准输入(replicateM 5 (readLn :: IO Integer))读取整数列表或生成所有可能的给定长度的布尔字符串(replicateM 5 [False, True])。如果在后一种情况下我后来决定用更有效的非确定性 monad 替换 list monad,我不想重写 replicateM
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-27
  • 1970-01-01
  • 1970-01-01
  • 2011-07-19
  • 2017-11-22
  • 2013-02-24
  • 1970-01-01
相关资源
最近更新 更多