robkuz
robkuz

Reputation: 9914

How do I properly override a constrained method

How do I override the method Zero in the following code in such a way that I can return Euro(0) for the definiton in the 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) :> _

Upvotes: 5

Views: 138

Answers (2)

Yawar
Yawar

Reputation: 11607

There is also the 'roll your own typeclass' technique in F#. Basically your abstract type's (instance and static) members become the fields of a 'typeclass' record, and values of that record are typeclass instances. You can have a 'euro' instance, a 'dollar' instance, and so on:

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>

The unique thing about F# is that the type parameter that is passed to each typeclass instance can actually be a measure type, which is appropriate for currencies.

Upvotes: 1

pblasucci
pblasucci

Reputation: 1778

Have you tried lifting the generic constraint to the class level?

[<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)

Though self-referencing generics always seems weird to me, this is how it'd be done in, for example, C#.

Upvotes: 7

Related Questions