如何正确覆盖约束方法

时间:2017-02-15 15:50:04

标签: f# type-constraints

如何覆盖以下代码中的方法Zero,以便我可以Euro(0)

返回type Euro的定义
[<AbstractClass>] 
type Currency () =
    abstract member Zero<'T when 'T :> Currency > : unit -> 'T

type Euro (value: int) =
    inherit Currency()
    member this.Value = value
    override this.Zero() = Euro(0) :> _

2 个答案:

答案 0 :(得分:7)

您是否尝试将通用约束提升到类级别?

[<AbstractClass>] 
type Currency<'T when 'T :> Currency<'T>>() =
    abstract member Zero : unit -> 'T

type Euro (value: int) =
    inherit Currency<Euro>()
    member this.Value = value
    override this.Zero() = Euro(0)

虽然自我引用的泛型对我来说似乎总是很奇怪,但这就是它的完成方式,例如,C#。

答案 1 :(得分:1)

在F#中还有'roll your own typeclass'技术。基本上,您的抽象类型(实例和静态)成员将成为“类型类”记录的字段,该记录的值是类型类实例。您可以拥有“欧元”实例,“美元”实例,等等:

module Currency =
  type t<[<Measure>] 'a> =
    { zero : decimal<'a>; from : decimal -> decimal<'a> }

  /// Helper function to easily create typeclass instances for any
  /// currency.
  let make<[<Measure>] 'a> (curr_unit : decimal<'a>) : t<'a> =
    { zero = curr_unit - curr_unit; from = ((*) curr_unit) }

  [<Measure>] type euro
  let euro : t<euro> = make 1m<euro>

  [<Measure>] type dollar
  let dollar : t<dollar> = make 1m<dollar>

关于F#的独特之处在于,传递给每个类型类实例的类型参数实际上可以是一种适用于货币的度量类型。