Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top