Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mixin or trait in F#

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.

like image 994
Paul Nikonowicz Avatar asked Jul 13 '12 18:07

Paul Nikonowicz


2 Answers

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 opened 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.

like image 133
Daniel Avatar answered Nov 16 '22 03:11

Daniel


Ruby mixins are best emulated with extension methods (type extensions) in the .NET framework. I don't believe F# has any special language features that more closely resemble mixins, traits, or multiple inheritance.

See this question: How do I create an extension method (F#)?

And this description: http://msdn.microsoft.com/en-us/library/dd233211.aspx

For speed's sake, here's the example given on MSDN:

module MyModule1 =

    // Define a type.
    type MyClass() =
      member this.F() = 100

    // Define type extension.
    type MyClass with
       member this.G() = 200

module MyModule2 =
   let function1 (obj1: MyModule1.MyClass) =
      // Call an ordinary method.
      printfn "%d" (obj1.F())
      // Call the extension method.
      printfn "%d" (obj1.G())
like image 37
ken Avatar answered Nov 16 '22 01:11

ken