Skip to content
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

Support anonymous record types [ RFC FS-1030 ] #207

Closed
baronfel opened this issue Oct 20, 2016 · 47 comments
Closed

Support anonymous record types [ RFC FS-1030 ] #207

baronfel opened this issue Oct 20, 2016 · 47 comments

Comments

@baronfel
Copy link
Contributor

baronfel commented Oct 20, 2016

Submitted by Howard Mansell on 3/24/2014 12:00:00 AM
215 votes on UserVoice prior to migration

Commonly I want to return some named values, or sequence of named values, in some expression. Currently I am forced to either go through the additional effort of defining a type, or use a tuple (with its associated error-proneness if there are multiple values of the same type). Anonymous record types would be very useful and would eliminate one of the areas of additional verbosity compared to C#.

Original UserVoice Submission
Archived Uservoice Comments

RFC is here: https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1030-anonymous-records.md

@dsyme dsyme changed the title Support C#-like Anonymous Types in F# Support C#-like anonymous types Oct 29, 2016
@kflu
Copy link

kflu commented Jan 11, 2017

This is also useful in template rendering (nustache,razor), where the model data can be casually passed in as an anonymous type instance in c#: new {Foo="foo", Bar="bar}

@jpierson
Copy link

I really do enjoy this feature in C# and the ability to return them from functions in TypeScript. The fact that F# doesn't have this concept surprised me because of the extensive use of type inference in other places I guess I just expected it was there until I went reaching for it.

@dsyme
Copy link
Collaborator

dsyme commented Jan 15, 2017

Archived comments:

Ah just realized this is being tracked at the following link now. #207

Jeffrey PiersonJeffrey Pierson commented · January 13, 2017 21:47 If voting wasn't close I would +3 for this. I really do enjoy this feature in C# and the ability to return them from functions in TypeScript.

Tomas LyckenTomas Lycken commented · September 05, 2016 15:05 I'd love this! See http://stackoverflow.com/q/39306148/38055 for a use case.

Bruno BozzaBruno Bozza commented · August 16, 2016 02:39 This is badly needed for data wrangling over typed datasets. I tried to use F#, which I prefer for everything else, but when every 5 lines of query code induce a new record type, updating the records becomes tedious very quickly, so I am back to C# for this. C#'s support is not perfect (or new), but it has really convenient record punning. And for the drastic cuts they had to make in the design (i.e.: anonymous types being non-denotable and limited to method scope), my favorite feature of this design is that it allowed the team to ship it, and now I can use it. Yes, I expect more from F#, but I would be happy to give up on structural subtyping, first class labels and even denotability, in order to get C#-style functionality.

Yemi BeduYemi Bedu commented · June 01, 2016 23:08 What is the expectation for these types to shadow each other? Would you want the compiler to warn about a named record that matches your anonymous one in certain use cases? Examples would be anonymous record of { Length:int ; Width:int } that could be in a lot of places. Another example is if you describe a Point { X:int ; Y:int } and later the anonymous version gets used in a function. Should it infer Point or just warn "a named record of type Point matches"? Would we want the allow declaration signatures to be anonymous

let Girl = {Name: string ; Age: int } 
let Boy = {Name: string; Age: int } 
let greet (child: {Name;Age}) = printfn "%A" child.Name

greet {Name="you";Age=21}

Don SymeDon Syme commented · February 05, 2016 11:21 See also this suggestion on StructTuple compatible with C# tuples: http://fslang.uservoice.com/forums/245727-f-language/suggestions/6148669-add-support-for-structtuple

Don SymeDon Syme commented · February 05, 2016 11:11 See also this suggestion which is somewhat related http://fslang.uservoice.com/forums/245727-f-language/suggestions/8107647-extend-with-keyword-support-to-record-definition

Ben LappinBen Lappin commented · September 18, 2015 17:13 One benefit is that if you're only using a type in one place, somewhere deep inside a let binding, you currently need to define the type prior to the outermost let, which can be inconvenient. Take the following example:

type Thingy = { Inty: int; Stringy: string } 
let .... 
let .... 
let aThingy = { Inty = 5; Stringy = "F# is fun" }

It would be preferable to be able to write something like:

let.... 
let.... 
let aLocalThingy = { Inty: int = 6; Stringy: string = "Future F# is funner" }

...and in either case, you could then do what you needed with the record, as long as the flow of code allowed its (anonymous) type to be inferred. Essentially I would see this as "syntactic sugar" over defining a type that will only be used in one place.

Jari PennanenJari Pennanen commented · June 24, 2015 06:54 Anonymous Records (which is a same thing as propsed here) are really neat, they are basically like TypeScript interfaces, allowing structural typing where it makes sens. Scala (library) implementation: http://downloads.typesafe.com/website/presentations/ScalaDaysSF2015/T4_Vogt_Compossible.pdf Above Scala implementation has some really great benefits, potentially shortening typesafe SQL syntax a lot. Haskell (library) implementation https://gist.github.com/nikita-volkov/6977841 not very familiar with this one, but that is where I took the name.

MichaelMichael commented · November 12, 2014 23:21 What's the benefit here? Creating anonymous types, just to turn around and use reflection on them seems sort of hacky. C# APIs like ASP.NET MVC use this because they don't have any slick way of doing [ "prop1", "val1"; "prop2", "val2" ].

Christopher StevensonChristopher Stevenson commented · July 04, 2014 08:43 If the issue with this idea is syntax, here's a thought: "new with { property1 = value; property2 = value }". The "new with" indicates that this is an anonymous record.

Anonymous commented · June 21, 2014 23:58 For a bit of historical perspective, structural record types were part of Standard ML decades before C#.

Eamon NerbonneEamon Nerbonne commented · June 21, 2014 09:22 I think this would go particularly well with destructuring let bindings for records - (http://fslang.uservoice.com/forums/245727-f-language/suggestions/6081483-allow-destructuring-let-bindings-for-records-or-t).

Eamon NerbonneEamon Nerbonne commented · June 21, 2014 09:01 Swift's solution isn't very good, however, so let's not copy that. in particular, swift's names don't really matter, it's still just a positional tuple, so when you do a destructuring let binding, you bind by position, not name. If you happen to swap the names (or mistype one, or refactor and change a member's name), then swift will still let you destructure by position, ignoring the names.

Maciej J. BańkowskiMaciej J. Bańkowski commented · June 05, 2014 15:54 @joel Mueller, I have created a pull request for Neo4jClient that includes support for tuples: DotNet4Neo4j/Neo4jClient#56 It is not perfect but works as a workaround for the lack of anonymous types. BTW I totally agree F# should support something like anonymous record types. I do not know why this comes up so late in the F# dev cycle but the requirement to create one-time-use types to work with data is hard for me to understand. As @lev Gorodinski noted, dynamic has major drawback in that it relaxes strong typing which is a very important F# feature we should keep. Does anyone know if there is any technical issue preventing implementation of anonymous types in F#?

ManuelManuel commented · June 03, 2014 13:43 Swift just introduced that also with named member tuples

Joel MuellerJoel Mueller commented · April 22, 2014 17:51 You can't use the dynamic operator in a quotation, however. There are some C# libraries (such as Neo4jClient) that expect LINQ expression trees that create anonymous types, and extract property names and data types from the expression tree. An F# equivalent is only possible if the dynamic operator is usable in a quotation, or if F# supports anonymous types.

Lev GorodinskiLev Gorodinski commented · March 24, 2014 13:26 An alternative is to use a dynamic operator https://www.nuget.org/packages/FSharp.Dynamic/ which can be useful for constructing values at application boundaries. For calls within an application, I would stick to explicit types though.

@smoothdeveloper
Copy link
Contributor

I find records are a reasonable fallback for not having anonymous type, maybe a good solution would be to declare types in scope of a let binding (I'd assume they'd have a mangled name in IL and eventually could be coallesced at assembly level).

I must say I haven't felt the lack of them in F# to be hindering me much albeit I tend to use them in C# (lack of short tuple notation?).

For me this is at most a nice to have feature, I'm looking for more C# converts to 👍 it.

@gusty
Copy link

gusty commented Jan 15, 2017

I do need them when working with intermediate data structure.

The alternative is either to use tuples or to declare out of the body of the functions all the intermediate records that are being used.

I know that struct tuples in C# will have named fields (erased at runtime), that's exactly what we need.
It was mentioned at the beginning that this feature will also be available in F# subjected to the C# design, but C# design it's complete and looks like nothing happened.

This is unfortunate because it's F# rather than C# who needs this feature. C# has already anonymous records types.

Specifically I just had a situation with a customer where I proposed F# as language for migrating a huge set of web scraping scripts to .Net, but the fact that it doesn't support anonymous types didn't convince the customer to use F# instead of C# and unfortunately I don't have any argument against that because he's right, it will be more verbose and will require more maintenance since each time there is a change in the fields there must be edited in two different places.

@smoothdeveloper
Copy link
Contributor

@gmpl does having ability to define local types come close to this?

AFAIR anonymous types in C# don't have structural equality so I wouldn't qualify those as anonymous records.

Coming on par / compatible with named fields in tuples from C# would be a great thing.

It seems for this feature (or the first shot) to generate more appeal, it should iron out the details more:

  • can the types escape the member they are defined?
  • do they coallesce at assembly level and if so, based on what?
  • can they be defined as struct as well?
  • do they have all the same attributes as records (structural equality, with syntax to create new ones)

Can a type provider solution help in your specific context? I know it sometimes helps with maintenance and schema changes in similar contexts.

@gusty
Copy link

gusty commented Jan 15, 2017

@smoothdeveloper You're right, I used the wrong word, I wanted to say "anonymous types" and I know it's not exactly the same but at least they have a mechanism available. Now they have two, we still have zero.

Type providers are vey limited in this scenario, because normally the data is not in the shape you will store it, you have to collect it, un-pivot it so you need some intermediate structures, in each step you do data transformation, that way is easy to debug/test it.

Type providers help in the case where the data already has more or less the shape you expect or in the initial step, but then you need to transform it and also perform some validations.

If you are interested I can show you some examples, you'll see how important is to have named tuples available.

@smoothdeveloper
Copy link
Contributor

smoothdeveloper commented Jan 15, 2017

@gmpl, thanks I understand and agree that anonymous types are a nice feature for this use case.

This seems like a not so small feature, apparently lots of vote for it in uservoice :)

@dsyme
Copy link
Collaborator

dsyme commented Jan 15, 2017

@gmpl @smoothdeveloper I do feel the lack of this feature when doing data-centric programming in F#

Putting aside syntax, the fundamental issues with anonymous types are

  1. are they represented by a real class (with proper field/property names for reflection) and accessed by IL field/property calls ?
  2. if (1), and assuming no changes to the CLR, then the name of that class is necessarily tied to an assembly. So are anonymous types even compatible across assembly boundaries? If so, is access, creation etc. efficient across assembly boundaries?
  3. if (1) is this class representation fully compatible with C# anonymous types, and/or C# POCO types, and/or F# record types, and/or C# tuple types.
  4. if not (1) then can access be made efficient
  5. how do they interact with generalization.
  6. do they support structural euality/comparison

For now, assume a syntax like

  • data(Name="abc",Id=123) or
  • anon(Name="abc",Id=123) or
  • {# Name="abc",Id=123 #} or
  • {| Name="abc",Id=123 |} or
  • d(Name="abc",Id=123) or
  • anon{Name="abc; Id=123} or
  • new{Name="abc"; Id=123 } or
  • new(Name="abc", Id=123) or whatever.

For point 2, the question is whether let f1() = new(Id=3) and let f2() = new(id=4) create compatible types, including

  • if declared within the same function (e.g., if two branches of an if/then/else create compatible types)
  • if declared in the same assembly
  • if declared in different assemblies.

If "yes" to all, then access to the types is necessarily going to have to be via a dynamic mechanism (at least when it is not possible to determine which assembly the type is declared in, along with a canonical stable mangled name for the type). I do feel a mechanism to ensure "fast access" across assembly boundaries would be sensible.

For point 5 above, the question is whether let f x = new(Name=x) would generalize. - if so, then a generic class is needed under-the-hood.

@gusty
Copy link

gusty commented Jan 16, 2017

@dsyme I don't think we need them to be compatible across assembly boundaries, the idea behind anonymous types is that they are short-lived types used internally in a method.
Now, what's a method boundary? That's clear in C# but I know it is not in F# since that's a compilation detail.

Anyway, don't you think that right now for F# is better to concentrate in having C# named StructTuples instead?
They will have structural equality and maybe we can make them compatible with C# by being able to read/write the metadata the C# compiler emits for the names.

I would love to see this feature, if it's too late for F# 4.1 at least for the updates.

@dsyme
Copy link
Collaborator

dsyme commented Jan 16, 2017

I don't think we need them to be compatible across assembly boundaries.

From a language design perspective, I would be pretty upset to have assembly-boundary identity for these types. I think that just sucks in all sorts of ways, though I understand it may cover many use cases.

the idea behind anonymous types is that they are short-lived types used internally in a method

That's the C# design idea. But it's fundamentally flawed and only justifiable through the self-justifying circle of "that's how C# does it so it must be right" or even "that's all we could do given the design of the CLR even though the guys down the corridor control the design of the CLR". It certainly encourages larger methods and makes refactoring large code into smaller reusable methods difficult.

Anyway, don't you think that right now for F# is better to concentrate in having C# named StructTuples instead? They will have structural equality and maybe we can make them compatible with C# by being able to read the metadata the C# compiler emits for the names.

Perhaps. However I find the named-field-of-tuples-via-attribute-metadata feature very "smelly" in C#. There are many cases where the lack of reflection on property names will make these worse than useless (e.g. LINQ queries mapping to actual table names; or serializing using Json.NET, or pushing the objects across to a UI, or the lack of debugging introspection except in cases where additional analysis is possible to recover the field names etc. etc.). The use of partial erasure makes them smell like Java generics. It's also not clear how widely they will be adopted in API design. And even if widely, it's not clear if they will be respected and loved as part of good API design.

Aside: TBH it's very odd from a language design perspective for C# to introduce non-reflection-friendly types in such a fundamental construct so late in the day, at version 7.0, when so many C# tools depend on using reflection well. It's honestly like one of the fundamental design principles of C# has been forgotten along the way: things like anonymous types were designed very much with reflection in mind. For F#, we also use reflection a lot, e.g. in pretty-printing output using %A or FSI, or for all the same scenarios as C#.

I would love to see this feature, if it's too late for F# 4.1 at least for the updates.

Definitely far, far too late for F# 4.1! More like 4.2 or 4.3 or 5.0

@smoothdeveloper
Copy link
Contributor

C# anonymous types are immutable, opposite of recently added struct tuples.

If there is no overhead, we should consider making those feel like records or struct records as they are well known to F# users and have some advantages (structural comparison and with syntax).

@smoothdeveloper
Copy link
Contributor

@dsyme, there is a feature of CLR for making type with same representation accross different assemblies work like the same type, but I don't recall the name, maybe that would be useful to remove the "all sorts of ways" the C# anonymous types aren't so great?

It is used in VS extension development and I think it came with .NET 4.5.

@jpierson
Copy link

jpierson commented Jan 16, 2017

My interest in anonymous records is to have them treated very much like I can in TypeScript where I can return adhoc typed objects from functions and have those functions signatures including the return type inferred at compile time. What I'd like to be able to do is stuff like the following.

let createAHappyOne name = new { name; mood = "Happy" }
let createASadOne name = new { name; mood = "Sad" }

let printOne one = printf "%s is a in a %s mood" one.name one.mood

Without the ability to deal with the values outside of the scope of a function I think usage would be related to the same cases it is currently within C# which helps but doesn't seem to cover several other interesting cases.

Ideally having these be able to cross assembly boundaries would be nice to but only from a type inference perspective as no name would be available to use as a hint. Perhaps the underlying name could be derived from the first function that returns the type. For example it would be nice to be able to have createAHappyOne in assembly A and printOne in assembly B.

I would expect these values to be immutable, having the ability to have either struct or ref type, and yes having structural equality like anonymous types in C# makes sense. Sorry if my post is light on the technical side but I just wanted to express my reason for supporting the feature and what I was hoping to expect out of it.

@smoothdeveloper
Copy link
Contributor

in C# they are not structurally equal, at least in C# interactive:

var a = new[] { new { a = 1 }, new { a = 1 } };
a[0] == a[1]
// false
a[0].GetType() == a[1].GetType()
// true

@dsyme
Copy link
Collaborator

dsyme commented Jan 16, 2017

Perhaps the underlying name could be derived from the first function that returns the type

I do think this some rule like this may be plausible and practical, and at least allow all types of all data to be named,inferred and used across assembly boundaries.

When compiling to Javascript then these limitations would presumably be liftable.

Other options are mangling data_name_T_mood_string; or hashing based on field names and type names data_3672929 (in practice collisions would be incredibly unlikely if a decent hash function is used). Such names would of course be implicit - you would never use them explicitly. All would implicitly be assembly-qualified - if using an anonymous type implied from another assembly you'd have to add the assembly name as a qualifier somehow.

@jpierson
Copy link

jpierson commented Jan 16, 2017

@smoothdeveloper, perhaps structural equality is not the correct term but what I mean is that for C# the following works because anonymous types automatically override Equals and GetHashCode to give the effect of structural equality. I rarely use == in c# unless I know I'm working with basic value types or a class where I have directly overridden the operator otherwise it is assumed that it is always reference equality such as with strings.

var a = new[] { new { a = 1 }, new { a = 1 } };
object.Equals(a[0], a[1]);
// true

Which makes me curious about how F# record types behave in C# on whether they override == operator or not or how that even makes sense to override an operator when interoping between CLR languages.

Update: Based on the details here it looks like overriding the == operator doesn't come through in F# records. Additionally I learned that in F# there appears to be LanguagePrimitives.PhysicalEquality to test for referential equality. The only way to access the == operator specifically in F# seems to be to using it's reflection name op_Equality unless there are other methods I'm unaware of.

@Hermholtz
Copy link

@smoothdeveloper

in C# they are not structurally equal, at least in C# interactive:

a[0] == a[1]

this compares references. Structural equality check is:

a[0].a == a[1].a

and is, of course, true.

@smoothdeveloper
Copy link
Contributor

@chojrak11 what I mean is this (tried in C# interactive):

var a = new { a = 1 };
var b = new { a = 1 };
a.GetType() == b.GetType()
// true
a == b
// false

@Hermholtz
Copy link

Hermholtz commented Feb 15, 2017

So this is referential integrity, not structural. C# by default compares references, and a and b are objects allocated on heap, not values (structs in F#).

@smoothdeveloper
Copy link
Contributor

@chojrak11 yes, I was stating anonymous types in C# aren't structurally comparable, and in the context of this feature request some peolpe compared them to F# records (which are), I was asking the question "do we want F# anonymous types as discussed in this feature suggestion to be structurally comparable?".

I hope this clarifies why I brought structural equality and the lack of support in C#.

I'd want F# anonymous types discussed here to be structurally comparable by default, what do others think?

@Overlord-Zurg
Copy link

@smoothdeveloper I would go so far as to amend the feature request to "anonymous record types" (implying structural comparability). At least I think that's what I would want from this feature.

@jpierson
Copy link

Here are a handful of StackOverflow questions I could find as evidence of real world friction people are running into especially around Linq.

http://stackoverflow.com/q/8144184/83658
http://stackoverflow.com/q/31909234/83658
http://stackoverflow.com/q/8546823/83658
http://stackoverflow.com/q/21879859/83658
http://stackoverflow.com/q/26961004/83658
http://stackoverflow.com/q/8650463/83658
http://stackoverflow.com/q/13991448/83658

@dsyme
Copy link
Collaborator

dsyme commented Mar 1, 2017

@jpierson Thanks for that list

I must admit I struggle with this issue in F#. I want the language to have anonymous record types, but can't settle on the right tradeoff to make. It's one of the things that continually niggles away at me as I think about the language design.

@dsyme
Copy link
Collaborator

dsyme commented Mar 10, 2017

@sgoguen Could you move those comments to the RFC discussion thread please? Thanks!

fsharp/fslang-design#170

@dsyme dsyme added the needs rfc label Dec 1, 2017
@dsyme dsyme changed the title Support anonymous record types (including C# compat) Support anonymous record types (including C# compat) [ RFC FS-1033 ] Dec 1, 2017
@dsyme dsyme changed the title Support anonymous record types (including C# compat) [ RFC FS-1033 ] Support anonymous record types [ RFC FS-1030 ] Dec 1, 2017
@dsyme
Copy link
Collaborator

dsyme commented Dec 1, 2017

RFC: https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1030-anonymous-records.md

@Thorium
Copy link

Thorium commented May 3, 2018

I can write nested functions, so why can't I write nested types?

let f x = 
   let g y = y + 5
   g x

let f x = 
   type MyThing = ...
   let g y = y + 5
   g x

For .NET library usage reasons the classes are sometimes large e.g.

type MyClass() as this =
    inherit SomeFrameworkLibraryType<SomeContext>()
    member __.AThing() =
      async {
        // 30 lines...
      }

    // 300 lines...

    member __.NThing() =
      async {
         // Instead of tuple, let me just write the return type near the usage
         // I don't care if it's named tuple, anonymous, or whatever
         // I just want to write it here, and not 400 lines up.
         // If not here, can I write it before `NThing()`, not before the whole class?
         return (x1, y1, z1, x2, y2, z2, ...)
      }

@kflu
Copy link

kflu commented May 3, 2018

Note that C# recently added another language feature that can serve a similar purpose (among others) - the named tuple:

var thing = (age: 11, name: "john", home: "LA");
Console.WriteLine(thing.name);

@xperiandri
Copy link

Is there an option to bypass structural equality?
Have you also thought about named tuples?

@jpierson
Copy link

@xperiadri, I would assume that Object.ReferenceEquals would work for testing reference equality.

@dsyme
Copy link
Collaborator

dsyme commented Oct 12, 2018

Note that C# recently added another language feature that can serve a similar purpose (among others) - the named tuple:

@kflu Yes and no. The C# named-tuple feature uses non-standard metadata representations that mean the metadata is not available via normal .NET reflection. This unfortunately means we're going to see a mess where people extract the metadata from attributes using non-standard and no doubt buggy techniques. It's an unfortunate situation that I fear will gradually lead to the over-complexifying of code that supports reflective inspection.

Have you also thought about named tuples?

This is covered in the RFC.

@cartermp
Copy link
Member

cartermp commented Nov 6, 2018

The PR has been merged: dotnet/fsharp#4499

@cartermp cartermp closed this as completed Nov 6, 2018
@cartermp cartermp added this to the F# 4.6 milestone Jan 21, 2019
@SchlenkR
Copy link

SchlenkR commented Apr 8, 2019

What About

Records using implied field names {| x.Name; Age = 31 |} instead of {| Name=x.Name; Age=31 |}

which is mentioned in the RFC? Should we open up a new Suggestion item for this? The Extension seems unobstrusive to me, but would improve my workflow (mainly FSI + working with data).

@cartermp
Copy link
Member

cartermp commented Apr 8, 2019

@ronaldschlenker Can you file a new issue with a use case stated?

@SchlenkR
Copy link

SchlenkR commented Apr 9, 2019

Ah, I just saw that there is already #653 that covers the proposal. The last comment if from April 2018. Feel free to close #734. Anyway, I'm willing to help implementing...

@blumu
Copy link

blumu commented Aug 9, 2019

@cartermp @dsyme I realize this issue is closed but I am just hitting an exception when consuming a anonymous record across assembly boundary, and it's not clear to me after reading the RFC (https://github.com/fsharp/fslang-design/blob/master/FSharp-4.6/FS-1030-anonymous-records.md#cross-assembly-working) and reading through the above thread whether it was decided that this should be a fully supported scenario in F# 4.6. Could you confirm?

Here is the exception that I get, the type is defined in assembly FSharpLu.Test and consumed in FSharpLu.Test.Azure which throws:

Message: 
    System.TypeLoadException : Could not load type '<>f__AnonymousType1008046745`1'' from assembly 'FSharpLu.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
  Stack Trace: 
    at AzureQueue Fibonnaci Test@55.Invoke(Unit unitVar)
    at AsyncPrimitives.CallThenInvoke[T,TResult](AsyncActivation`1 ctxt, TResult result1, FSharpFunc`2 part2)
    at Trampoline.Execute(FSharpFunc`2 firstAction)
    at --- End of stack trace from previous location where exception was thrown ---
    at TaskAwaiter.ThrowForNonSuccess(Task task)
    at TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at --- End of stack trace from previous location where exception was thrown ---
    at TaskAwaiter.ThrowForNonSuccess(Task task)
    at TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
    at --- End of stack trace from previous location where exception was thrown ---
    at TaskAwaiter.ThrowForNonSuccess(Task task)
    at TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

https://github.com/microsoft/fsharplu/blob/78062b867206d2badab380b8ab44358f85552725/FSharpLu.Azure.Test/ActorAzureQueueSchedulerTest.fs#L52

I am happy to provide more details in a separate issue if this is confirmed to be a bug.

@cartermp
Copy link
Member

@blumu This should indeed be fully supported. Can you submit a bug report to https://github.com/dotnet/fsharp ?

@dsyme
Copy link
Collaborator

dsyme commented Aug 16, 2019

@blumu This should indeed be fully supported. Can you submit a bug report to https://github.com/dotnet/fsharp ?

Do we have a tracking bug for this yet? I definitely want to understand it

@blumu
Copy link

blumu commented Aug 21, 2019

@dsyme @cartermp Thanks for the response. Good news: shortly after I posted my message, I was able to work around the bug by tweaking some of the type definitions in my code.
Bad news: I am now unable to repro this exception... I remember that I was doing something stupid like defining a type alias for an anonymous record (e.g. type Foo = {| field : int |} instead of just type Foo = { field : int }) and at the time, this appeared to be the cause for the System.TypeLoadException exception I was getting. Trying this now, however, does not cause any problem... I might give it another try later this week. I'll create a new bug if I manage to repro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests