Implement a C# Interface in F# - 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!

Related

F# constructor constraint

Whilst attempting to learn the use of constructor constraints, I was hoping that something like the following was possible.
type Foo<'T when 'T : (new : int -> 'T)> = {Bar: 'T}
But this does not compile, simply returning the error
'new' constraints must take one argument of type 'unit' and return the constructed type
It seems as though the constraint should be called "parameterless constructor constraint" because I cant get any other form beyond this to compile.
type Foo<'T when 'T : (new : unit-> 'T)> = {Bar: 'T}
Can a constructor constraint be used to constrain the generic types constructor to have a specific signature other than unit ?
As noted in the comments, .NET support for constraints is limited and only supports (i) paremeter-less constructors and (ii) implementation of an interface.
F# follows the same restructions for ordinary generic type parameters, but it also has statically resolved type parameters written as ^T, which can have more expressive constraints. Those are not compiled to .NET constraints, but instead, are erased during the compilation, so there are other constraints on those.
An example akin to what you have using static memnber constraints would look something like this:
type Foo<'T> =
{ Bar : 'T }
static member inline Demo< ^S when ^S : (static member Create : int -> ^S)>() =
{ Bar = (^S : (static member Create : int -> ^S) (10)) }
The constrains need to be on an inline member (or inline function), so I'm defining a generic type Foo<'T> which has a static member Demo that can be called with any type that has a Create method taking an int. For example:
type Sample(n:int) =
member x.N = n
static member Create(n:int) = Sample(n)
We can now call Foo.Demo with Sample as the type argument and we get Foo<Sample> back, created using 10 as the initialization value:
let f = Foo<_>.Demo<Sample>()

Why can I pass two parameter to Event class

When I look the definition of event class in f#
type Event<'T> =
class
new Event : unit -> Event<'T>
member this.Trigger : 'T -> unit
member this.Publish : IEvent<'T>
end
I can pass only one type on event class like
let nameChanged = new Event<unit>()
But I saw some sample too, that pass two variables like
let propertyChanged = Event<PropertyChangedEventHandler, PropertyChangedEventArgs>()
How could be that be possible?
And when I implement an interface like
module SapHandler
open SAP.Middleware.Connector
type Connector() =
let configurationChanged = Event<RfcDestinationManager.ConfigurationChangeHandler, RfcConfigurationEventArgs>()
interface IDestinationConfiguration with
member self.ChangeEventsSupported() =
false
[<CLIEvent>]
member self.ConfigurationChanged = configurationChanged.Publish
The compiler complain:
The type 'RfcDestinationManager.ConfigurationChangeHandler' has a non-standard delegate type
Why?
The definition of delegate type is:
It's possible because there's another class too:
type Event<'Delegate,'Args (requires delegate)> =
class
new Event : unit -> Event<'Delegate,'Args>
member this.Trigger : obj * 'Args -> unit
member this.Publish : IEvent<'Delegate,'Args>
end
You're getting that error because your delegate for the event is probably missing the first object sender argument which is standard in .net. You can use Control.DelegateEvent<'Delegate> to get around this
let propertyChanged = DelegateEvent<RfcDestinationManager.ConfigurationChangeHandler>()

Can't correctly implement XNA interface IUpdateable in F# because of events

I'm currently using F# and XNA for my new project, but got stuck when implementing XNA's IUpdateable interface. Specifically when I need to implement the event handlers.
This is what I have:
let enabledChanged = new DelegateEvent<System.EventHandler>()
and further down:
interface IUpdateable with
... // other stuff
[<CLIEvent>]
member self.EnabledChanged = enabledChanged.Publish
But i'm getting this error:
Error 2 This expression was expected to have type EventHandler but here has type EventHandler<EventArgs>
I've tried several things but can't get this to work. What is expected to be there?
Thanks in advance!
Have you tried defining enabledChanged in the following way?
let enabledChanged = new Event<_>()
as I see IUpdatable.EnabledChanged has type System.EventHandler<System.EventArgs> but you are using System.EventHandler without type parameters.
type X() =
let enabledChanged = DelegateEvent<EventHandler<_>>()
interface IUpdateable with
[<CLIEvent>]
member this.EnabledChanged = enabledChanged.Publish
type Y() =
let enabledChanged = Event<EventHandler<_>, _>()
interface IUpdateable with
[<CLIEvent>]
member this.EnabledChanged = enabledChanged.Publish

Can I use the 'use' keyword with object expressions?

I'm using an object expression to implement two interfaces. One of the interfaces is IDisposable. I expected to be able to use the 'use' keyword with the results from this object expression, but I get an error:
Type constraint mismatch. The type
IConnMan is not compatible with type
IDisposable The type 'IConnMan' is not
compatible with the type
'IDisposable'
Why do I get this error?
let connectionstring = "context connection=true"
let connman () =
let conn = new SqlConnection(connectionstring)
conn.Open()
{ new IConnMan with
member x.Connect () = conn
member x.Disconnect c = ()
interface IDisposable with
member x.Dispose() =
conn.Close()
conn.Dispose()
}
...
let f() =
use cn = connman() // <-- Error!
An object expression can have just a single type. The type is the type of the first (main) implemented interface - in your case, that's the IconnMan type. F# doesn't allow you to use use, because it doesn't statically know that the result of connman function is IDisposable.
You could create interfaces in the object expression in the opposite order:
let connman () =
let conn = new SqlConnection(connectionstring)
conn.Open()
{ new IDisposable with
member x.Dispose() =
conn.Close()
conn.Dispose()
interface IConnMan with
member x.Connect () = conn
member x.Disconnect c = () }
Then you could write use cn = connman() but you couldn't use functions of IConnMan without casting (this is essentially the same as doing what Desco suggests). I don't think there is any nice solution to this problem.
Could your IConnMan interface inherit from IDisposable?
F# spec says:
Object expressions are statically checked as follows.
First, ty0 to tyn are checked and must all be named types. The overall type of the expression is ty0 and is asserted to be equal to the initial type of the expression. However, if ty0 is type equivalent to System.Object and where ty1 exists, then the overall type is instead ty1.
so you can use type tests and downcasts or change the sequence of interfaces being implemented so IDisposable will be first
let f() =
use cn = connman() :?> IDisposable

Generics with interfaces in F#

In C# one can state that a generic parameter must implement a certain interface like so:
public class Something<T> where T : IComparable
{
...
}
How does one specify this in F#?
Generic constraints use "when" in F#:
type Foo<'a when 'a :> IComparable> =
member x.Bla = 0

Resources