How to use the base implementation of an overridden abstract member? - f#

There are an interface (say IA), an implementation (say Base) of the interface IA, and a derived class of Base (say Derived) which overrides an abstract member of IA. Now, in the implementation of the overridden member, I want to use the implementation of the member of Base. However, I don't know how to write to do so.
This code illustrates my question:
type Flag =
| F1 = 1
| F2 = 2
type IA =
abstract member A: Flag
type Base() =
interface IA with
member this.A = F1
type Derived() =
inherit Base()
interface IA with
override this.A = (* ? *)
// base.A ||| F2 // NG (Compile error that `A` isn't a member of `base`)
// (base :> IA).A ||| F2 // NG (Syntax error)
// (this :> IA).A ||| F2 // NG (Infinite recursion)

I actually think there is no way to do this. F# interface implementations are similar to explicit interface implementations in C# and you cannot call base implementation of an explicitly implemented interface in C#.
The workaround is to modify the base class so that it is more like C# implicit interface implementation (which is sadly a bit cumbersome):
type Base() =
// Define virtual property in class Base
abstract A : Flag
default this.A = Flag.F1
// Implement IA via the virtual property
interface IA with
member this.A = this.A
type Derived() =
inherit Base()
// Override the virtual property
override this.A = base.A ||| Flag.F2
The following now returns 3 as expected:
(Derived() :> IA).A

Related

Finding classes implementing an interface, using reflection, and instantiating them in F#

I am trying to achieve the following:
I have an interface, called IBotCommand and a few classes that implement it. I want to find all these classes, through reflection, instantiate an instance of each and put the result in a dictionary.
the interface is the following:
type IBotCommands =
abstract member Name: unit -> string
abstract member Description: unit -> string
abstract member Help: unit -> string
abstract member Execute: MessageEventArgs -> string[] -> string
and the code:
let t = typeof<IBotCommands>
t.Assembly.GetTypes()
|> Seq.filter (fun x -> x.IsSubclassOf(t))
|> Seq.iter (fun x ->
(
let i = Activator.CreateInstance(x) :> IBotCommands
botCommands.[i.Name] <- i
)
)
the issue I have is with the CreateInstance line. CreateInstance returns an obj type that can't be cast to IBotCommands.
I have the same in C# and it works properly but the C# version is using dynamics:
public static IEnumerable<Type> FindClassSubclassOfType<T>()
{
var a = typeof(T)
.Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(T)))
.Select(t => t);
return a.ToList();
}
var types = ReflectionHelper.FindClassSubclassOfType<BotCommand>();
foreach (var t in types)
{
dynamic c = Activator.CreateInstance(t);
BotCommands[c.Name] = c;
}
how can I get this behavior to work in F#?
can you cast an object to an interface in F#? it's my first time using interfaces in F#
In F#, there is a difference between upcast a :> T and downacst a :?> T.
Upcast is used when the compiler statically knows that a implements an interface T. This is useful if you have a value of a concrete class and want to get a value that has a type of an interface.
Downcast is used when the compiler does not statically know whether a implements an interface. In other words, this means that the cast can fail.
In your case, you need a downcast, because the compiler does not know whether obj implements IBotInterface. All you need to do is to add ?:
let i = Activator.CreateInstance(x) :?> IBotCommands
botCommands.[i.Name] <- i

How to make an Abstract class that inherits an interface in F#?

I have the following code with an interface and an abstract class.
type INode<'a> =
abstract member Parent:INode<'a>
abstract member Evaluate:unit->'a
abstract member Clone:INode<'a> -> INode<'a>
abstract member SelectRandom:int->INode<'a> option
[<AbstractClass>]
type TerminalNode<'a>() =
interface INode<'a> with
member this.SelectRandom indexOfCurrentNode =
let p = 1.0 / float indexOfCurrentNode
if Random().NextDouble() < p then Some (this:>INode<'a>) else None
I want to implement the hierarchy in this
but the compiler complains that all methods of the interface should be implemented.
What is the correct way to create an Abstract class that implements an interface and implements that interface's one method leaving other methods abstract?
Note: If you cannot see the image, your network is blocking imgur.com.
You can define the abstract members on the type, then provide the implementation which points at those abstract members. For example:
[<AbstractClass>]
type TerminalNode<'a>() as self =
abstract member Parent : INode<'a>
abstract member Evaluate : unit->'a
abstract member Clone:INode<'a> -> INode<'a>
interface INode<'a> with
member this.Parent = self.Parent
member this.Evaluate () = self.Evaluate ()
member this.Clone a = self.Clone a
member this.SelectRandom indexOfCurrentNode =
...
(note the as self in the type line, which lets you refer to the abstract type by the variable name self)

F#: Implementing an interface with overloaded members

I have defined an interface in F# with an overloaded method. As per compiler request, the overload uses tupled arguments instead of curried ones:
type IInterface =
abstract member Do : (int * string) -> unit
abstract member Do : int -> unit
I then create a class which implements the interface:
type ImplementingClass =
interface IInterface with
member this.Do (i, s) = ()
member this.Do i = ()
However, doing so yields the compiler error for the first of both methods: "This override takes a different number of arguments to the corresponding abstract member"
What am I doing wrong here?
There is a subtle difference between the following two:
abstract member Do : int * string -> unit
abstract member Do : (int * string) -> unit
If you add the parentheses, you're saying that the parameter is a tuple and the compiler should produce a method taking Tuple<int, string>. Without parentheses, the method will be compiled as taking two parameters. Most of the time, this is hidden and you can ignore it - but sadly, not always.
So, you can either change your interface definition to use ordinary "two-parameter" method (this would be my preferred method - you can still call the method with tuple as an argument and looks nicer in the .NET/C# view):
type IInterface =
abstract member Do : int * string -> unit
abstract member Do : int -> unit
type ImplementingClass =
interface IInterface with
member this.Do (i, s) = ()
member this.Do i = ()
Or you can implement the interface as it is:
type ImplementingClass =
interface IInterface with
member this.Do((i:int, s:string)) = ()
member this.Do(i:int) = ()
Sadly, this is a bit ugly - you need the type annotations so that the compiler can unambiguously decide which method you're implementing.

Implement a C# Interface in F#

I have the following interface in C#
public interface IDog
{
String Bark();
}
I want to create an implementation in F#. I had no problem with this:
type GermanShepherd() =
interface IDog with
member this.Bark() = "Woof"
but when I added a supporting function that is not part of the interface like this:
type GermanShepherd() =
interface IDog with
member this.Bark() = "Woof"
member this.Eat() = "Yummy"
the compiler complained:
Error 1 No abstract or interface member was found that corresponds to this override
Error 2 This value is not a function and cannot be applied*
Is there a way of implementing private/internal functions with a type that implements an interface without those functions being part of the interface? I can't change the interface in my 'real' application b/c there are other projects that implement the interface. None of the examples on MSDN that I found have this particular scenario.
The interface block should only contain functions that are part of the interface, but you can place other functions before the block:
type GermanShepherd() =
member this.Eat() = "Yummy"
interface IDog with
member this.Bark() = "Woof"
If you do not need a public member, then you can go with a private let-bound function:
type GermanShepherd() =
let eat() = "Yummy"
interface IDog with
member this.Bark() = "Woof"
Also note that F# currently only allows explicit interface implementations, which means that you can treat GermanShepherd as IDog, but you won't see IDog members explicitly:
let g = GermanShepherd()
g.Eat() // OK
g.Bark() // Error, interface members are implemented explicitly
let d = g :> IDog // To 'Bark', we need to get 'IDog' first
d.Bark() // OK
One workaround for this is to add the Bark method explicitly as a separate member outside of the interface block. Although there is F# language issue for this too!

Is this an F# bug?

I have an type that is implementing IEnumerable<T> interface, all is ok:
open System
type Bar() =
interface Collections.IEnumerable with
member x.GetEnumerator () = null
interface Collections.Generic.IEnumerable<int> with
member x.GetEnumerator () = null
But things goes wrong if type inherits IEnumerable interface implementation via the base type:
open System
type Foo() =
interface Collections.IEnumerable with
member x.GetEnumerator () = null
type Bar() =
inherit Foo()
interface Collections.Generic.IEnumerable<int> with
member x.GetEnumerator () = null
Code above produces the type inference errors:
The member 'GetEnumerator<'a0 when 'a0 : null> : unit -> 'a0 when 'a0 : null' does not have the correct type to override any given virtual method
The member 'GetEnumerator<'a0 when 'a0 : null> : unit -> 'a0 when 'a0 : null' does not have the correct number of method type parameters. The required signature is 'GetEnumerator : unit -> Collections.Generic.IEnumerator<int>'.
Am I doing something wrong or this is an F# compiler bug?
Microsoft (R) F# 2.0 Interactive build 4.0.30319.1
Update more canonical example:
type IFoo = abstract Bar : obj list
type IFoo<'a> = abstract Bar : 'a list
inherit IFoo
/* ok */
type Foo = interface IFoo with member x.Bar = []
interface IFoo<Foo> with member x.Bar = []
/* fail */
type FooBase = interface IFoo with member x.Bar = []
type FooDerived = interface IFoo<Foo> with member x.Bar = [] // <---
inherit FooBase
/*
error FS0017: The member 'get_Bar : unit -> 'a list' does not
have the correct type to override any given virtual method.
*/
The compiler cannot infer the correct type from your "null"-implementation. Try
open System
type Foo() =
interface Collections.IEnumerable with
member x.GetEnumerator () = null
type Bar() =
inherit Foo()
interface Collections.Generic.IEnumerable<int> with
member x.GetEnumerator () : Collections.Generic.IEnumerator<int> = null
UPDATE:
The reason is, that the type of the GetEnumerator method implemented by the Bar type is ambigous as IEnumerable<'a> implements/inherits the non-generic IEnumerable which also specifies a (non-generic) GetEnumerator method. So, how should the compiler infer, which method exactly you are trying to implement if all he gets is null? Therefore we need a type annotation in this case.
This is not a bug, this is just an type inference fail because of F# may implement inherited interface members in the derived interface implementation declaration:
type IA = abstract A : int
type IB = inherit IA
type IC = inherit IB
type Baz =
interface IC with
member x.A = 1
So in my example I should specify the correct return type explicitly because member x.GetEnumerator() in derived Bar type may match both IEnumerable.GetEnumerator() and IEnumerable<T>.GetEnumerator().

Resources