-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Request: make C# 7's discriminated unions compatible with F# #9039
Comments
You mean they should take a dependency on F# runtime lib? That's beyond unacceptable, if anything, a C# AST for option type might find its way to BCL and then it's F# that should maintain compatibility with it. I agree that this will be really helpful but it adds unnecessary burden to C# design. I think since BCL is written in C#, this should be taken care of on F#'s side. |
How would you propose that the |
While I see the convenience in having compatibility between the two languages F# currently produces some quite specific types to accomplish pattern matching and expects some very specific conventions. To actually achieve this goal of compatibility would require that C# effectively implement pattern matching identically to F#, which I doubt is the goal of the C# team. |
I've been toying around with this a little and I've been unsuccessful at defining a C# class that F# will recognize as an ADT as is. I started with a public F# definition in a library and copied the structure as closely as possible yet F# still balks. This includes all of the F# If compatibility between the two languages does become a worthwhile goal (and I do see the utility of it) I think that the two teams should collaborate over the public interface of what makes an ADT. Future versions of the F# compiler could adhere to this convention. Also, for the concerns with |
I didn't realise the F# team switched their tuple model when they were added to the BCL. That does indeed suggest they could switch |
@DavidArno: As far as I know, F# was still in beta then. It is of course a breaking change as the namespace of the type changes. At least when doing C# interop. Within F#, it probably wouldn't matter. |
F# was released as 1.0 in 2005 but the BCL didn't get tuples until 2010. You can still target F# projects to previous versions of the .NET framework and it will fallback to the tuple classes in FSharp.Core.dll. But those tuple classes were at least defined in the System namespace. Update: FSharp.Core.dll does define the assembly-level attributes to forward Unfortunately F#'s |
Just to mention, F#'s option is not a regular DU and it has been specialized (e.g. |
I like the idea of DU's being structs, but I've got hung up on the syntax. Assuming we are going for the following syntax for class DU's: abstract sealed class DU
{
type 1 def;
type 2 def;
...
} Then what do we put for structs? The following seems silly, as abstract sealed struct DU
{
type 1 def;
type 2 def;
...
} Whilst the compiler could be modified to accept that combination as a way of telling it I'm declaring a DU, it seems clunky. But hang-ups on syntax ugliness seems a very poor reason to not inplement DU's as structs. |
I believe what you're missing is the undocumented |
@svick I had noticed that resource and suspected that it (or other assembly level metadata) might be involved. It's weird that F# uses both that and type/member attributes to specify that metadata, you'd think that there'd be enough information by simply examining the type. Anyhow, I think that demonstrates that it wouldn't be suitable for C# to produce F#-compatible ADTs. But I do think that there would be value in the two teams collaborating together to decide on a compatible contract going forward. |
FYI, wrote a blog post about valuetype discriminated unions... While I'm more in favor of valuetype for performance reasons, we could have a syntax that could support both options. |
@xoofx Great post! That's something along the lines of #6739. A minor point: It'd be nice if
|
For the explicit layout problem with T , this can be solved by packing non T-blitable types into a internal struct with explicit layout, and place T types/object types on their own slots. The structured enum would not be declared with an ExplicitLayout, only parts of its internal representation/packing. So suppose you have a type like this: public struct enum Variant<T>
{
V1(int x),
V2(float y, T add),
V3(object z)
} The generated parent struct public struct Variant<T>
{
protected $PackedStruct $packed; // used by V1.x and V2.y
protected T $field1; // used by V2.add
protected object $field2; // used by V3.z
[StructLayout(LayoutKind.ExplicitLayout) struct $PackedStruct{ [FieldOffset(0)] int x; [FieldOffset] float y; }
} |
Re the comment on your blog:
Are these two things truly mutually exclusive? I see two potential options here:
|
@DavidArno indeed, as I responded later to a user comment, I don't mind having both, as long as we have a valuetype DU. It would make actually the compatibility possible (though I would not project it the same way F# is doing it today, by avoiding |
@xoofx In your example |
@alrz ah! maybe, haven't checked actually... 😅 but yeah, putting it outside will solve the issue. |
Discussion should continue at dotnet/csharplang#485 |
Assuming C# 7 supports discriminated unions, then, if I define the following in F#:
then C#'s pattern matching features should support that type as a sealed ADT type set and it should handle it just as if I'd defined it in C# as:
If possible, the two definitions should generate the same IL.
Further, whilst there will likely be practical problems around this extra idea, the
option
type inMicrosoft.FSharp.Core
should be used by the new pattern matching features to, for example, avoid having to useout
parameters with the newis
operator as discussed in #9005.The text was updated successfully, but these errors were encountered: