Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# and interface-implemented members

I have a vexing error.

type Animal =

    abstract member Name : string

type Dog (name : string) =

    interface Animal with

        member this.Name : string =
            name

let pluto = new Dog("Pluto")
let name = pluto.Name

The last line, specifically "Name" generates a compiler error saying that "the field, constructor or member 'Name' is not defined".

The workaround I've used is to write

let name = (pluto :> Animal).Name

However this is very annoying and creates a lot of visual noise. Is there something one can do in F# to just be able to resolve Name without telling the compiler explicitly that Name is a derived member from the Animal type?

like image 540
Bent Rasmussen Avatar asked Jan 29 '13 23:01

Bent Rasmussen


2 Answers

In F#, when you implement an interface, it's an equivalent of explicit interface implementation in C#. That is, you can call the method through the interface, but not directly through the class.

F# reference article about interfaces suggests adding a method that does the upcasting to the type:

type Dog (name : string) =

    member this.Name = (this :> Animal).Name

    interface Animal with
        member this.Name : string = name

Or, as suggested by Daniel, you can do it the other way around, which means you can avoid that cast:

type Dog (name : string) =

    member this.Name = name

    interface Animal with
        member this.Name : string = this.Name

Also, the .Net convention for interface names is to start them with I, so your interface should be called IAnimal.

like image 71
svick Avatar answered Nov 19 '22 08:11

svick


Another option is to use an abstract class instead of an interface:

[<AbstractClass>]
type Animal () =
    abstract Name : string

type Dog (name) = 
    inherit Animal()
    override dog.Name = name

let pluto = Dog("Pluto")
let name = pluto.Name
like image 44
Phillip Trelford Avatar answered Nov 19 '22 07:11

Phillip Trelford