【问题标题】:Does F# have row polymorphism (or something similar?)F# 是否具有行多态性(或类似的东西?)
【发布时间】:2015-04-09 07:00:36
【问题描述】:

F# 是否具有行多态性或类似的东西?具体来说,在 OCaml 中,我们可以写一个类似的函数

# let foo x = x#num+2;;
val foo : < num : int; .. > -> int = <fun>

基本上,函数foo 可以接受任何包含num 类型int 的方法的对象。我不确定如何在 F# 中做类似的事情。如果可能的话,我想避免通过继承进行显式子类型化。具体来说,我不是在寻找这样的东西:

[<AutoOpen>]
module Foo

[<AbstractClass>]
type foo() =
    abstract member num : int

type foo1() =
    inherit foo()
    override this.num = 2
    member this.char = 'a'

type foo2() =
    inherit foo()
    override this.num = 3
    member this.string = "abbacadabba"

let f (x:foo) = x.num + 2

原因是即使我们可以在f 中使用foo1foo2 类型的对象,我们也无法分别访问它们的其他成员charstring。为了重新获得这些信息,我们必须使用双重调度技巧,例如访问者模式,我正在努力避免这种情况。基本上,我试图获得类似行多态性而不是子类型的东西。

【问题讨论】:

标签: .net f# ocaml f#-3.0


【解决方案1】:

这是一种方法:

let inline foo (a: ^a) = 
    let x = (^a : (member num: int) (a))
    x + 2

type monkey() =
    member x.num = 2
type pig() =
    member x.num = 3

let x = monkey()
let y = pig()

foo x // = 2+2=4
foo y // = 3+2=5

【讨论】:

  • 感谢您的示例。从上面@CarstenKönig 的评论中,我了解到这些是明确的成员约束。现在,语法(^a : (member num: int) (a)) 是否有名称,或者这与显式成员约束有内在联系?基本上,我们是否使用这种向后的语法在其他任何地方调用对象的类型?
  • @Carsten König,重新编辑,new 是可选的,但我不知道有任何指南说它不应该使用,你能指出我正确的方向吗?
  • @PatrickMcDonald 老实说现在我无法提供官方来源,但 AFAIK 它是惯用的 - 如果您不使用 new 和 IDisposables,编译器会警告您,这是一件好事have - new 会告诉读者这是一种应该处理的资源,编译器会帮你找到它,...
  • spec6.4.1 基本应用程序表达式 中隐含声明 new 关键字被认为是可选的:应用程序表达式可以以对象构造表达式开头不要包含new 关键字...
  • 顺便说一下,在回答我自己的问题时,语法(^a : (member num: int) (a)) 被规范称为成员约束调用表达式,在第6.4.8 节中。
猜你喜欢
  • 2010-10-22
  • 2017-12-08
  • 2014-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-30
  • 2011-04-05
相关资源
最近更新 更多