Is there a simpler way to use interfaces in F# implicitly? - interface

I am playing a bit with F# interfaces, by creating a simple data access class.
The interface is:
type IUserAccess =
abstract member GetUsers : (dbSchema.ServiceTypes.Users -> bool) -> dbSchema.ServiceTypes.Users seq
abstract member GetAllUsers : unit -> dbSchema.ServiceTypes.Users seq
In the class, I am calling the methods in this way:
type UserAccess() =
let db = dbSchema.GetDataContext()
interface IUserAccess with
member this.GetUsers cond =
let query = query {
for row in db.Users do
select row }
query |> Seq.where cond
member this.GetAllUsers () =
(this:>IUserAccess).GetUsers (fun _ -> true)
What I'm a bit concerned with is the way I am calling GetAllUsers function, specifically with part (this:>IUserAccess). What is the simplest way of calling methods that are implemented within the same interface?
One simple option I can think of is creating GetUsers method directly within UserAccess() class and then calling it from the interface implementation of both GetUsers and GetAllUsers, but that means a new private method implemented, which I would like to avoid. Is there another option?

I think the solution by #vcsjones is probably the best option if you want to avoid defining a separate method directly inside the class. That said, declaring a separate method is actually not that ugly. You can use local definition using let binding (which is automatically compiled as a private method) and I think it makes the code look quite nice:
type UserAccess() =
let db = dbSchema.GetDataContext()
let getUsers cond =
let query = query {
for row in db.Users do
select row }
query |> Seq.where cond
interface IUserAccess with
member this.GetUsers cond = getUsers cond
member this.GetAllUsers () = getUsers (fun _ -> true)
I generally quite like this style, because it separates all the private implementation from the part of the definition where you're defining the public exposed API.

F# always implements interfaces explicitly, so your options are pretty much as you stated, but you can avoid redundant casting by introducing a let binding:
type IUserAccess =
interface
abstract member GetUsers : (obj -> bool) -> unit
abstract member GetAllUsers : unit -> unit
end
type Foo() as self =
let userAccess = self :> IUserAccess
interface IUserAccess with
member this.GetUsers(q : (obj -> bool)) : unit =
()
member this.GetAllUsers() =
userAccess.GetUsers(fun _ -> true)
I just simplified your interface and object so I could get something compiling real quick.

Related

Derive functions with interface - F#

I'm new to F# and I'm trying to implement a little calculator with these interfaces...
But I'm struggling with the derive part as soon as i get to f_add.
Would be nice if someone could help me out. :)
type IFunction =
interface
abstract member ToString: Unit -> String
abstract member Apply: Nat -> Nat
abstract member Derive: Unit -> IFunction
end
Since f_add is defined in curried form (typical for F# functions), and not tupled, you need to pass the arguments with spaces, not as a tuple:
// HERE . Using comma makes that a tuple
// member self.Derive () = f_add(f.Derive (), g.Derive ()) //wrong
Instead, pass as an F# style function:
member self.Derive () = f_add (f.Derive ()) (g.Derive ())
The same issue exists in the other implementations.

F# interface syntax to declare a function with byref returned object (or Tuple), like Int32.TryParse

I'm not able to find how to declare a function in an interface so that I have a Tuple or byref result.
I want to simulate this syntax:
let executed, value = Int32.TryParse("123")
Let's say that I have a function with 2 input parameters and I want to know if the result is successful and in case having the result (a Record type in this case). Kind of:
type Result = {reference:string; value:decimal}
type IExecutor =
abstract member DoStuff: (aa:string) * (bb:string) * (result:byref<Result>) -> bool
abstract member DoStuff: (aa:string, bb:string, result:byref<Result>) -> bool
type Executor () =
member this.DoStuff (aa:string, bb:string, result:byref<Result>):bool =
result <- {reference="ref"; value=0m}
false
let executed, result = executor.DoStuff "aa" "bb"
or
let executed, result = executor.DoStuff("aa", "bb")
I'm not able to declare DoStuff in the interface.
The second try is a copy of the Int32.TryParse signature I see from intellisense, why doesn't work?
What is the correct syntax for having DoStuff called as I want ?
First of all to declare an interface you use abstract members and you only apply the signature
type IExecutor =
abstract member DoStuff: string*string*outref<int>->bool
If you want to implement the interface it goes as follows
type Executor() =
interface IExecutor with
member this.DoStuff (a:string,b:string,result:outref<int>) : bool =
result <- 3
true
You can call it like this
let s = new Executor() :> IExecutor
let a,b = s.DoStuff ( "lorem" "ipsum" )
Having said that, if you're consuming this only from F# avoid outrefs use tuples:
type IExecutor =
abstract member DoStuff: string->string->bool*int
type Executor() =
interface IExecutor with
member this.DoStuff (a:string) (b:string) : bool*int =
true,3
let s = new Executor() :> IExecutor
let a,b = s.DoStuff "lorem" "ipsum"

Interfaces, generics and method overloading in F# and how to leverage its type inference

Background: I am trying to expand my existing logging framework, which is currently a wrapper of static non-thread-safe methods over printfn and friends. My design goals are: having a generic interface ILog and concrete classes like Dbg, Log, Trace. I cannot use modules and functions, unfortunately, because I like to leverage the ConditionalAttribute on the methods.
I have a working approach that looks something like this:
type ILog<'T, 'U, 'V> =
abstract member log: 'T -> unit
abstract member log: 'U * 'V -> unit
type Dbg<'T, 'U, 'V when 'T :> Printf.StringFormat<string> and 'U :> Printf.StringFormat<'V -> string>>() =
static member inline _do_other_stuff() = "other stuff"
static member inline private _helper() =
printfn "%s %s" (Dbg<_,_,_>._do_other_stuff())
interface ILog<'T, 'U, 'V> with
[<Conditional("DEBUG")>] // removed from call site
member this.log(msg) = sprintf msg |> Dbg<_,_,_>._helper()
[<Conditional("DEBUG")>] // removed from call site
member this.log(fmt, a) = sprintf fmt a |> Dbg<_,_,_>._helper()
module TestMe =
let test() =
let dbg = new Dbg<_,_,_>() :> ILog<_,_,_>
dbg.log("test%i", 2)
Here, the compiler and syntax checker and coloring detects properly the dbg.log("test%i", 2) line, which is exactly what I want. It will also properly raise an error if I were to write "test%s" instead.
Now, if I take the above approach and expand it to create more overloads of the ILog.log method, this gets pretty hairy pretty quickly because of all the type annotations and the required use of syntax like Dbg<_,_,_>. Some of it can be hidden away, but still I figured there must be a better way.
One approach I tried, which seemed very FSharpish is:
type ILog =
abstract member log: _ -> unit
abstract member log: _ * _ -> unit
This compiles the interface and infers the type to be 'a0 and 'a0 -> 'a1 respectively (which seems wrong, why is the second log member getting the same 'a0?). But, I can't find any way of implementing such overly generic interface:
type Dbg() =
interface ILog with
member this.log v = v + 1 |> ignore // it won't infer int here
It raises:
The declared type parameter '?' cannot be used here, since the type parameter cannot be resolved at compile time.
Does F# 4.0 have a way of declaring interfaces in a more generic way, or am I stuck to having to declare them specifically (while this works, it is tedious).

Creating and using a generic function in a non generic F# interface

It is beyond me at this point. I'm trying to create an interface that looks something like
this.
type IFetchData =
abstract FetchData: string -> seq<'a>
The above declaration is valid (and compiles) but when I go to use it I get a compile time error. This expression was expected to have type 'a but here has type "what I'm currently trying to return" i.e. seq.
My example usage however looks like the following:
type SampleFetchData() =
interface IFetchData with
member self.FetchData str =
seq {
for letter in str do
yield letter // compile error here
}
I'm not sure what I'm doing wrong. All I'd like to do is allow the interface implementer to be able to write any function that returns a generic sequence either seq<string>,seq<int>,seq<record type here>, seq<union type here>, etc.
Can someone tell me what I'm missing here?
Thanks.
If you're loading the interface implementation using Reflection, then it is going to be quite difficult to work with it. The problem is that you get an object of type obj. You know that it implements IFetchData<'T> for some 'T, but statically, you don't know for which 'T. This is a problem because you can't cast the object to any more specific type - if you tried using IFetchData<obj>, it wouldn't work because you can't cast, for example, IFetchData<int> to that type.
I would recommend using a non-generic interface, which is quite common .NET pattern:
type IFetchDataUntyped =
abstract FetchData : string -> System.Collections.IEnumerable
type IFetchData<'T> =
inherit IFetchDataUntyped
abstract FetchData : string -> seq<'T>
When you load an implementation using Reflection, you can cast the object to IFetchDataUntyped and work with it in a fairly reasonable way (using Seq.cast to convert the sequence to a more specific type if you know the element type).
Depending on your application, you may also just make the FetchData method a generic method and keep the interface non-generic. Then you could cast dynamically loaded objects to the interface and invoke the method. However, this changes the design (because the method has to work for any type it gets as a type parameter):
type IFetchData =
abstract FetchData<'T> : string -> seq<'T> // Note: Generic parameter here!
You need to do something like
type IFetchData<'a> =
abstract FetchData: string -> seq<'a>
type SampleFetchData() =
interface IFetchData<char> with
member self.FetchData str =
seq {
for letter in str do
yield letter
}
i.e. the interface needs to be made generic. If you want to avoid the genericness you could use some inline constraints, rather than an interface
EDIT: Inline magic version
let inline Fetchdata string obj=
(^a: (member FetchData: string -> seq<'b> )(obj, string))
type SampleFetchData() =
member self.FetchData str =
seq {
for letter in str do
yield letter
}
Fetchdata "hello" (new SampleFetchData())

Implement equality outside type definition

I have several types that implement an interface. Equality for these types only depends on interface members. Is it possible to define equality for these types once, without overriding Equals or op_Equality for each type?
EDIT
I tried the following, but, for whatever reason, it overrode every use of =, even for types not implementing IEntity.
[<AutoOpen>]
module Equality =
let inline op_Equality (left:IEntity) (right:IEntity) = true
I also tried using flexible types (#IEntity). Same result.
What you're trying to do is something that mixins or typeclasses might enable in other languages; unfortunately there isn't equivalent functionality in F#. Your best bet is probably one of the following options:
Use an abstract base class instead of an interface.
Write your equality method outside of your type and then have all of your implementations defer to it. For example,
let entityEquals (i1:IEntity) (i2:IEntity) =
i1.Member1 = i2.Member1 &&
i1.Member2 = i2.Member2 &&
...
type MyEntity() =
interface IEntity with
member x.Member1 = ...
...
override x.Equals(y) =
match y with
| :? IEntity as y -> entityEquals x y
| _ -> false
override x.GetHashCode() =
...
In addition to a bit of boilerplate, the downside here is that if anyone else implements your IEntity interface, they aren't forced to use your equality method - it's opt-in.
Create an another operator which you use for equality testing of IEntitys:
let (==) (i1:IEntity) (i2:IEntity) =
i1.Member1 = i2.Member1 &&
...
The (huge) downside of this is that structural equality of types containing IEntitys (such as tuples, records, etc.) won't use this operator to compare those components, which is likely to lead to surprising broken code.
I don't think there is a way to do this in a static way. The problem is that extension members (e.g. if you added op_Equality as an extension) are ignored by static member constraints (e.g. if you also redefined = using inlin with op_Equality requirement).
The F# compiler has some special powers available only when compiling FSharp.Core.dll that could help (search sources for the declaration let inline GenericOne). It uses something like static type switch - but this cannot be accessed by mere mortals.
So, I don't have any idea better than using dynamic type test, which isn't really a good approach and it's probably better to define a custom operator for comparison of your interfaces.
For a reference, the ugly dynamic approach would be:
let inline (=) a b =
match a, b with
| :? IFoo as a, :? IFoo as b -> yourEquals a b
| _ -> a = b