mixin or trait in F#

f#, functional-programming

Solution

You can abuse `inline` and member constraints to do duck typing, which gets you some of the benefits of mixins. For example, you could translate this Ruby code (taken from this tutorial):

module Debug
  def whoAmI?
    "#{self.type.name} (\##{self.id}): #{self.to_s}"
  end
end
class Phonograph
  include Debug
  # ...
end
class EightTrack
  include Debug
  # ...
end
ph = Phonograph.new("West End Blues")
et = EightTrack.new("Surrealistic Pillow")
ph.whoAmI?  »   "Phonograph (#537766170): West End Blues"
et.whoAmI?  »   "EightTrack (#537765860): Surrealistic Pillow"

to this:

type Phonograph(id, name) =
  member x.Id : int = id
  override x.ToString() = name

type EightTrack(id, name) =
  member x.Id : int = id
  override x.ToString() = name

module Debug =
  let inline whoAmI x =
    sprintf "%s (%d) : %s" 
      (^T : (member GetType : unit -> Type) x).Name
      (^T : (member Id : int with get) x)
      (^T : (member ToString : unit -> string) x)

let ph = Phonograph(537766170, "West End Blues")
let et = EightTrack(537765860, "Surrealistic Pillow")

Debug.whoAmI ph //"Phonograph (537766170) : West End Blues"
Debug.whoAmI et //"EightTrack (537765860) : Surrealistic Pillow"

It has the (arguable) advantage over extension methods of not requiring a common base class or interface. Regarding your previous question about the `open` keyword, you could have several modules defining `whoAmI` and the one `open`ed last will shadow previous ones. In that way you can sort of "mix in" which module you want. The F# core library uses a similar approach with checked operators.

Problem

Is there a way to achieve a mixin in Ruby or a trait in Scala in F#? What i want is to basically copy one module into another so that it shares the other modules functionality but is closed for modification. Or, an OOP way of thinking about it, I want multiple inheritance except that the parent object can not be modified.

Original source

Related problems