Alexander Ryan Baggett
Alexander Ryan Baggett

Reputation: 2397

F# How to use an interface in a separate module

So I have been doing research on interfaces on F#. I have found these 2 articles on it. The MSDN and F# for fun and profit But unfortunately they are only skin deep.

UPDATED

here is my module with my interfaces

//open statements omitted for brevity

 module DrawingInterfaces =

    ///gets a string representation of the SVG code representation of the object
   type IRepresentable_SVG =
      abstract member getSVGRepresenation : unit -> string

//other interfaces omitted for brevity

Now within the same namespace and physical folder also I have this:

 type lineSet (x1off,x2off,y1off,y2off,x1,x2,y1,y2,rot,rotOff,count) =

    //tons of member vals omitted for brevity

  member val x1Start = x1 with get, set

  interface  DrawingInterfaces.IRepresentable_SVG with 
            member __.getSVGRepresenation() = 

                let mutable svg = ""
                let mutable currentx1 = x1Start
                svg

This used to give me 2 errors, before I was using the __. notation for the member. The first error was on the interface line. And a second on the member line. The errors were respectively:

The type 'IRepresentable_SVG' is not defined


This instance member needs a parameter to represent the object being invoked.

I was able to fix the first one by changing the file order. Thanks to John Palmer. The second one is nearly fixed./

After using the __ . notation I was able to get rid of the second error. However, now a new error pops up when I try to use type members in my interface implementation.

      let mutable currentx1 = x1Start

x1Start shows as not being defined. I need to be able to use values stored in my other members within my implementation.

Upvotes: 0

Views: 923

Answers (1)

Gene Belitski
Gene Belitski

Reputation: 10350

Let's first make it work and then point to your problems. I define below 2 separate modules in 2 separate .fs files within the same namespace Example for interface definition in module Example.DrawingInterfacesand interface implementation in module Example.UseInterface and also a console app that will use the interface from third (implicit) module Program. In my project correspondent code files are in the following order: DefInterface.fs, UseInterface,fs, Program.fs (I also made few idiomatic styling changes and more brevity omissions)

File: DefInterface.fs

namespace Example
module DrawingInterfaces =
   type IRepresentable_SVG =
      abstract member GetSVGRepresenation : unit -> string

File: UseInterface.fs

namespace Example
module UseInterface =
    type LineSet (x1) =
        member val X1Start = x1 with get, set
        interface DrawingInterfaces.IRepresentable_SVG with 
            member __.GetSVGRepresenation() = "test" + " " + __.X1Start.ToString()

File: Program.fs

open Example
open System

[<EntryPoint>]
let main argv =
    let lineSet = UseInterface.LineSet(5)
    let example : DrawingInterfaces.IRepresentable_SVG = lineSet :> _
    example.GetSVGRepresenation() |> printfn "%A"
    lineSet.X1Start <- 10
    example.GetSVGRepresenation() |> printfn "%A"
    0

Compile, run and make sure it works.

Now to problems in your code:

  • first error message stems from the need to refer to the full implemented interface name in UseInterface.fs, which is Example.DrawingInterfaces.IRepresentable_SVG although as both modules belong to the same namespace the Example prefix may be omitted
  • second error message points to the need of using instance method in implementation class UseInterface.LineSet, which is achieved by prepending self-identifier __. to the method signature

Finally, notice the usage of your interface in Program.fs that imports namespace, provides module names for definition and implementation respectively, and also explicitly casts implementation LineSet to IRepresentable_SVG.

EDIT: I've added X1Start property to the original LineSet to show how it can be used from interface implementation per question author's request. Now self-id __. is more involved and probably using self. or even this. instead would make more sense.

Upvotes: 4

Related Questions