Confusing implementation of F# CodeDom - f#

I'm trying to create a class and a method in it. For C# and VB, the CodeDom providers emit preditable output, but the F# CodeDom provider emits the following. I'm wondering why.
exception ReturnException8abef2fbb2404165b4b8690157bd3a49 of obj
exception ReturnNoneException8abef2fbb2404165b4b8690157bd3a49
type
// Hello
test = class
new() as this =
{
}
abstract my_method : unit -> unit
default this.my_method () =
()
end
Ignoring the exception stuff (I guess the provider is still a bit buggy), I'm curious as to why I get such a weird definition with new() as this, an abstract method and a default implementation. Am I missing something here?

The code generated by the CodeDOM generator is weird, but it is mostly valid F# code that compiles. As kvb points out, the definition of constructor is valid. It would be nicer if the CodeDOM provider generated code using implicit syntax, but that wouldn't work well if you had multiple constructors.
As for the exceptions, these are used to emulate imperative return construct (as in C#). For example, you cannot directly write the following in F#:
for(int i = 0; i < 10; i++)
if (i == 5) return;
So the CodeDOM generator uses exception to emulate return and try .. with to handle it.
The usual coding style in F# is simply a bit different from C#/VB and the CodeDOM data structures were designed mainly for C#/VB. If you want to generate nice F# code, then writing your own code generator may be a better idea. Alternatively, someone could create F# CodeDOM provider that wouldn't support all features, but would generate nice code.

This looks fine to me.
new() as this = {}
is just an empty default constructor, and the abstract method with default implementation is how you define a virtual method in F# (see section 8.14.2 of the spec).

Related

Is the FSharp.Data XML type provider generative or not?

(previously "using type provider from C#")
This should be easy to answer, and the underlying issue has be asked before, but I'm slightly confused about it, having dug into it, there's something I'm missing.
The Xml type provider in
https://fsharp.github.io/FSharp.Data/library/XmlProvider.html
is erased?
so the types in it can't be used from another assembly?
"Erasing Type Providers produce types that can only be consumed in the assembly or project they are generated from" (says the MS docs).
but if I define in one assembly this
module Xml
type Xml = FSharp.Data.XmlProvider<"""
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>""">
let foo () = Xml.Parse ("")
and in another assembly, reference the above assembly and go...
let x = Xml.foo ()
let s = x.From
this compiles...so if the MS docs are correct, the provider must be generative?
if I implement the same code in C#,
var x = Xml.foo();
var y = x.From;
then this code doesnt compiler
'XmlElement' does not contain a definition for 'From' and no accessible extension method 'From' accepting a first argument of type 'XmlElement'
which seems to imply its erased...or I need to do something else (I've included the same dependencies).
My hunch is its erased, but then how does the F# assembly compile?
(I want it to be generative to use from C# and VB).
As far as I can tell by looking at the source code, all the types provided by FSharp.Data are erased.
The XmlProvider type is defined by this line at https://github.com/fsharp/FSharp.Data/blob/master/src/Xml/XmlProvider.fs#L26
let xmlProvTy = ProvidedTypeDefinition(asm, ns, "XmlProvider", None, hideObjectMethods=true, nonNullable=true)
As you can see, the instantiation of the ProvidedTypeDefinition type does not include isErased=false.
The ProvidedTypeDefinition type has two constructors. See the signatures at https://github.com/fsprojects/FSharp.TypeProviders.SDK/blob/master/src/ProvidedTypes.fsi#L268-L275
Both constructors have an implementation including this line, which means that the provide type is erased by default:
let isErased = defaultArg isErased true
Without redesigning the XmlProvider, the only way you can consume it from C# is to wrap it in an F# class that exposes C#-friendly types. Not sure if that would result in a better design than just avoiding the type provider altogether.
Assuming by "erased" you mean being removed from the FSharp.Data Library? then XMLProvider its probably not removed from it because I just tried your code and it works in F# project (as you have also noticed).
Now about the C# project the thing is TypeProviders are a Fsharp specific thing, whatever magic F# compiler is doing to type check xml and access the From xml-node here is probably only exclusive to F#.
The type of you variable x here is FSharp.Data.Runtime.BaseTypes.XmlElement, looking at the documentation here and the source code here.
There doesn't seem to be any way of accessing the xml nodes in an OOP way. Its probably not meant to be accessed that way either. If you want to parse xml and read its nodes in C# there are plenty of other ways for that. One being XmlReader in System.Xml

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.

NSubstitute and FSharp - Mocking an FSharp Function

Given an interface that has a FSharp style function.
type IUseless =
abstract member Listify: string -> int -> string list
How would you mock the function?
let substitute = NSubstitute.Substitute.For<IUseless>()
substitute.Listify.Returns(??? what would even go here ???)
I wouldn't expect to be able to mock it like a normal method, or a value that contains a function (although that's sort of what it represents).
So I'm curious if anyone has successfully mocked an FSharp function with a typical .NET mocking library.
First: yes, you can totally mock this like a normal method:
let substitute = NSubstitute.Substitute.For<IUseless>()
(substitute.Listify "abc" 5).Returns ["whatevs"]
This works, because F# compiles this definition like a normal .NET method, despite the curried syntax. This is done partly for interop and partly for performance.
But second: if I were you, I would rather skip the whole NSubstitute business altogether and use inline interface implementation instead:
let substitute = { new IUseless with member x.Listify a b = ["whatevs"] }
This is cleaner, better typechecked, and a lot faster at runtime.

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 :-)

Looking for robust, general op_Dynamic implementation

I've not been able to find a robust, general op_Dynamic implementation: can anyone point me to one? So far searches have only turned up toys or specific purpose implementations, but I'd like to have one on hand which, say, compares in robustness to C#'s default static dynamic implementation (i.e. handle lots / all cases, cache reflection calls) (it's been a while since I've looked at C#'s static dynamic, so forgive me if my assertions about it's abilities are false).
Thanks!
There is a module FSharp.Interop.Dynamic, on nuget that should robustly handle the dynamic operator using the dlr.
It has several advantages over a lot of the snippets out there.
Performance it uses Dynamitey for the dlr call which implements caching and is a .NET Standard Library
Handles methods that return void, you'll get a binding exception if you don't discard results of those.
The dlr handles the case of calling a delegate return by a function automatically, this will also allow you to do the same with an FSharpFunc
Adds an !? prefix operator to handle invoking directly dynamic objects and functions you don't have the type at runtime.
It's open source, Apache license, you can look at the implementation and it includes unit test example cases.
You can never get fully general implementation of the ? operator. The operator can be implemented differently for various types where it may need to do something special depending on the type:
For Dictionary<T, R>, you'd want it to use the lookup function of the dictionary
For the SQL objects in my article you referenced, you want it to use specific SQL API
For unknown .NET objects, you want it to use .NET Reflection
If you're looking for an implementation that uses Reflection, then you can use one I implemented in F# binding for MonoDevelop (available on GitHub). It is reasonably complete and handles property access, method calls as well as static members. (The rest of the linked file uses it heavily to call internal members of F# compiler). It uses Reflection directly, so it is quite slow, but it is quite feature-complete.
Another alternative would be to implement the operator on top of .NET 4.0 Dynamic Language Runtime (so that it would use the same underlying API as dynamic in C# 4). I don't think there is an implementation of this somewhere out there, but here is a simple example how you can get it:
#r "Microsoft.CSharp.dll"
open System
open System.Runtime.CompilerServices
open Microsoft.CSharp.RuntimeBinder
let (?) (inst:obj) name (arg:'T) : 'R =
// Create site (representing dynamic operation for converting result to 'R
let convertSite =
CallSite<Func<CallSite, Object, 'R>>.Create //'
(Binder.Convert(CSharpBinderFlags.None, typeof<'R>, null)) //'
// Create site for the method call with single argument of type 'T
let callSite =
CallSite<Func<CallSite, Object, 'T, Object>>.Create //'
(Binder.InvokeMember
( CSharpBinderFlags.None, name, null, null,
[| CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) |]))
// Run the method and perform conversion
convertSite.Target.Invoke
(convertSite, callSite.Target.Invoke(callSite, inst, arg))
let o = box (new Random())
let a : int = o?Next(10)
This works only for instance method calls with single argument (You can find out how to do this by looking at code generated by C# compiler for dynamic invocations). I guess if you mixed the completeness (from the first one) with the approach to use DLR (in the second one), you'd get the most robust implementation you can get.
EDIT: I also posted the code to F# Snippets. Here is the version using DLR: http://fssnip.net/2U and here is the version from F# plugin (using .NET Reflection): http://fssnip.net/2V

Resources