F#: Implement an inline method (On Inteface) to avoid using a real type - f#

I'm trying to see if inline can be applied to an implemented method so that the specific type coming in doesn't have to be spelled out. I've done this with one off (Not inherited/implemented) methods, but trying to also do using an interface.
type public IBookInteraction =
abstract inline CreateBook : 'a -> MethodResult<BasicBookModel>
type public BookInteraction(?userInteraction) =
interface IBookInteraction with
member inline x.CreateBook(bookModel) =
let userId = (^a : (member UserId : Int32 with get) (bookModel))
MethodResult<BasicBookModel>()
I'm guessing there's a way to do this, but it doesn't work with a generic operator(?) in the interface method signature.

I don't believe it's possible to have abstract inline methods. Even if you could, your code wouldn't work, because your interface definition promises that users can call it with any 'a, but your implementation places a static member constraint on 'a - in a hypothetical world where F# supported abstract inline methods, the declaration of the method on the interface would also need to include the constraint.
In any case, to see why it's not possible for F# to support abstract inline methods, consider what inline means: the code that you write to implement the method will be essentially copied and pasted into the call site. However, with an abstract method, you don't know the concrete type that is defining the implementation of the method, so there's no way to figure out at compile time what code you're supposed to be inlining!

I think the correct answer is interface implementations may not be inlined. I'm not sure why it's allowed in the interface definition.

Related

F# generalization by overloading

Given the type
type T =
static member OverloadedMethod(p:int) = ()
static member OverloadedMethod(p:string) = ()
Let's suppose we want to create a generic function that resolves to the specific overload based on the type of the parameter. The most intuitive way would be
//Case 1
let inline call o = T.OverloadedMethod o //error
call 3
call "3"
but this, despite the inline definition, doesn't work and the compiler complains
Error FS0041 A unique overload for method 'OverloadedMethod' could not
be determined based on type information prior to this program point. A
type annotation may be needed. Candidates: static member
T.OverloadedMethod : p:int -> unit, static member T.OverloadedMethod :
p:string -> unit
We can achieve what we want though, for example using the "operator trick"
//Case 2
type T2 =
static member ($) (_:T2, p:int) = T.OverloadedMethod(p)
static member ($) (_:T2, p:string) = T.OverloadedMethod(p)
let inline call2 o = Unchecked.defaultof<T2> $ o
call2 3
call2 "3"
The F# compiler here does (apparently) some more work and doesn't simply fall back to the .NET resolution.
Yet, this looks ugly and implies code duplication. It sounds like Case 1 should be possible.
What technical reasons justify this behaviour? My guess is that there is some trade-off (perhaps with .NET interoperability), but couldn't find more information.
EDIT
From the posts I extract this as a reason:
"a trait call is an F# compiler feature, so there must be two different ways of writing a simple call and a trait call. Using the same syntax for both is not convenient because it might be confusing, some uses could arise where a simple call is compiled as a trait call accidentally".
Let's put the question in a different perspective:
Looking at the code, it really seems straightforward what the compiler should do:
1) call is an inline function, so defer compilation to the use site
2) call 3 is an use site, where the parameter is of type int. But T.OverloadedMethod(int) exists, so let's generate a call to it
3) call "3" like previous case with string in place of int
4) call 3.0 error as T.OverloadedMethod(float) doesn't exist
I would really like to see a code example where letting the compiler do this would be a problem that justifies requiring the developer to write the additional code for the trait call.
At the end of the day, isn't one of F# strengths "conciseness and intuitiveness"?
Here we are in presence of a case where it looks like it could be better.
The trade-offs stem from the fact that this it's a completely erased compiler trick. This means that:
C# code can't see (and take advantage of) any call2 function, it can only see your two $ method overloads.
All information about call2 is gone at runtime, meaning you couldn't invoke it through reflection, for example.
It won't show up in call stacks. This may be a good or a bad thing -- for example, in recent versions of the F# compiler, they've selectively inlined certain functions to make async stacktraces a bit nicer.
The F# is baked in at the call site. If your calling code in is assembly A call2 comes from assembly B, you can't just replace assembly B with a new version of call2; you have to recompile A against the new assembly. This could potentially be a backwards compatibility concern.
A rather interesting benefit is that it can lead to drastic performance improvements in specialized cases: Why is this F# code so slow?. On the flip side, I'm sure there are circumstances where it could cause active harm, or just bloat the resulting IL code.
The reason of that behavior is that T.OverloadedMethod o in
let inline call o = T.OverloadedMethod o
is not a trait call. It's rather simple .NET overloading that must be solved at the call site, but since your function type doesn't imply which overload to solve it simply fails to compile, this functionality is desired.
If you want to "defer" the overload resolution you need to do a trait call, making the function inline is necessary but not sufficient:
let inline call (x:'U) : unit =
let inline call (_: ^T, x: ^I) = ((^T or ^I) : (static member OverloadedMethod: _ -> _) x)
call (Unchecked.defaultof<T>, x)
Using an operator saves you many keystrokes by inferring automatically these constraints but as you can see in your question, it requires to include a dummy parameter in the overloads.

How do you write a generic F# delegate declaration?

So, how do you write a generic delegate declaration in f#?
I want to get the equivalent of this c# declaration:
public delegate Result<TOutput> Parser<TInput, TValue>(TInput input);
I haven't been able to find documentation on how this might be achieved, even though it's a quite common to have to write generic delegates.
Any ideas or pointers?
You can define a generic delegate as follows:
type Parser<'TInput, 'TOutput> = delegate of 'TInput -> Result<'TOutput>
In F#, the generic parameters are written with a single quote at the beginning (to distinguish them from normal types), so that's why you need'TInput.
Just for the record, I don't think I ever needed to define a delegate in F#. I guess they are still useful for C# interop, but even then, I would probably just define a type alias for a Func delegate, or (when you are not going to be calling this from C#, just an ordinary F# function):
// Alias for a standard .NET delegate
type Parser<'TInput, 'TOutput> = System.Func<'TInput, Result<'TOutput>>
// Alias for a normal F# function
type Parser<'TInput, 'TOutput> = 'TInput -> Result<'TOutput>

Delay the implementation of interface methods?

I've been programming in F# for some years and there's an "issue" that's been bothering me for some time and I have not been able to solve. It is not a bug, I think it is a design decision, but anyway, the problem is this: is there a way to delay (maybe that's not the correct word for this) the implementation of interfaces?, that is, not implementing them in the initial definition, but later, maybe in the same file after I have implemented a module for the type. I'll explain with a simplified example:
Suppose I have the following data structure:
type 'T MyCollection =
(*type definition*)
interface IEnumerable<'T> with
member this.GetEnumerator () =
(* I don't want to implement it here
because I still don't have the module
with a toSeq function *)
If I implemented the method right there, I would have to also implement all the functions as methods of the type and then the module would be just a "proxy" for calling the methods. This way I'm creating a OO-first data structure and then creating a module (overloaded with type annotations) to allow for a functional-first usage. I would prefer to write a functional-first data structure (cleaner since the type inference can work better) and then create a OO wrapper to allow a better intellisense support for languages like C#. That approach complies with what the design guidelines for F# tells us, but the interfaces can't be implemented anywhere but in the initial definition of the type. That restriction forces me to write the whole data structure with members.
I've been looking for examples and I've found that the list implementation in FSharp.Core list does exactly what I want, but I can't do that, the compiler won't let me.
I'm almost sure that this is a design decision, maybe to avoid encouraging bad practices, I don't know, but I don't consider my wish to be a bad practice. Also I'm well aware of the linear nature of the fsharp compiler.
Please if any of you know how to do what I want, I'll be glad if you tell me. Also, if any of you know why I should not follow this approach I'll be glad to know too. There must be a reason why this is not a problem for anyone else.
Thanks in advance.
I completely agree that this is unfortunate problem. The trick that is used in the source code of 'a list in the F# Core library is to define the implementation of the interface in a type augmentation. The compiler does not complain when you add members to a type in this way, but it says that adding implementation of an interface in this way is deprecated. However, it does not prevent you from doing this. The following compiles fine for me:
open System.Collections
open System.Collections.Generic
type MyCollection<'T> =
{ Data : 'T list }
interface IEnumerable<'T>
interface IEnumerable
let getEnumerator { Data = d } =
(d :> seq<_>).GetEnumerator()
type MyCollection<'T> with
interface IEnumerable<'T> with
member this.GetEnumerator() = getEnumerator this
interface IEnumerable with
member this.GetEnumerator() = (getEnumerator this) :> _
The fact that this is deprecated is a bit unfortunate. I quite like this style and I use it when it makes sense. You can start a discussion about this on F# user voice and perhaps it could be turned back into a normal accepted feature :-)

F#: Implementation of interface that returns reference to iterator

I am implementing the Microsoft.VisualC.StlClr IVector and one of the member functions returns a reference to an iterator, like so
abstract begin :
:ContainerRandomAccessIterator<'TValue> byref -> unit
Would someone know how this interface function could be implemented?
B.
after looking at this interface in Reflector I'd rather say that it is impossible to implement it in F#. Method begin (as well as some other methods) has custom required modifier IsUdtReturn (modreq[IsUdtReturn]) and it seems it is not recognized by F# compiler. However I'll be glad to know that I'm wrong.

Unknown need for type annotation or cast

I know I must be missing something really obvious here. B.GetInstance().Call() generates the error: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
I'm using v1.9.9.9.
type A() =
member x.Call() = B.GetInstance().Call()
and B() =
static member GetInstance() = new B()
member x.Call() = ()
I just discovered that this works: (B.GetInstance() :> B).Call()
Any idea why the cast is necessary?
Frequently when you've got a recursive set of methods whose types to infer, F# needs help. A more pleasant alternative would be to annotate the definition of B.GetInstance:
type A() =
member x.Call() = B.GetInstance().Call()
and B() =
static member GetInstance() : B = new B()
member x.Call() = ()
I believe that the reason you run into this problem is that F# tries to solve all inferred types on all methods in A and B simultaneously (because they are defined as mutually recursive types), and this leads to problems, but perhaps someone from the F# team will weigh in.
The quick summary is that in a recursive group (e.g. members in one type, or members of recursive types like we have here) F# reads the declarations in left-to-right top-to-bottom order, followed by the definitions in left-to-right top-to-bottom order. So in this instance when it reaches the definition of A.Call, it has not yet read the definition of B.GetInstance and therefore does not (yet!) know that the return type of GetInstance will be B.
Keith's answer nails it for this situation, you can provide a type annotation to specify the return type of GetInstance in its declaration.
See
Forcing F# type inference on generics and interfaces to stay loose
for a deep discussion of what's going on here.
Note also that in your original attempt, you don't need to "cast" (the potentially dynamic operation, using :>), instead you can just "annotate" (statically declare a type, using :) to get it to compile. But makes more sense to put the type annotation in the method declaration for GetInstance (generally, prefer addition annotations to method signatures instead of arbitrary places inside bodies).

Resources