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.
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.
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())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With