{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/6739","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/6739/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/6739/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/6739/events","html_url":"https://github.com/dotnet/roslyn/issues/6739","id":116634590,"number":6739,"title":"Proposal: Record Enum Types","user":{"login":"alrz","id":3105979,"avatar_url":"https://avatars.githubusercontent.com/u/3105979?v=3","gravatar_id":"","url":"https://api.github.com/users/alrz","html_url":"https://github.com/alrz","followers_url":"https://api.github.com/users/alrz/followers","following_url":"https://api.github.com/users/alrz/following{/other_user}","gists_url":"https://api.github.com/users/alrz/gists{/gist_id}","starred_url":"https://api.github.com/users/alrz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alrz/subscriptions","organizations_url":"https://api.github.com/users/alrz/orgs","repos_url":"https://api.github.com/users/alrz/repos","events_url":"https://api.github.com/users/alrz/events{/privacy}","received_events_url":"https://api.github.com/users/alrz/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Area-Language%20Design","name":"Area-Language Design","color":"5319e7"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Feature%20Request","name":"Feature Request","color":"fc2929"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":21,"created_at":"2015-11-12T20:36:09Z","updated_at":"2015-11-17T01:21:07Z","closed_at":null,"body":"## Record Enum Types\r\n\r\nCurrently, `enum` types would be considered as complete patterns but they don't have any \"record\" syntax to be used in pattern matching. This proposal tries to fill this gap.\r\n\r\nThis proposal won't affect regular `enum` types like #3704, rather, it suggests an `enum`-like syntax for declaring flat hierarchies of ADTs (with both value and reference types).\r\n\r\n### Enum structs\r\n\r\n*Enum structs* would be more like Java enum types, for example\r\n\r\n```cs\r\npublic enum struct Color(int R, int G, int B) {\r\n\tBlue(0,0,255),\r\n\tGreen(0,255,0),\r\n\tRed(255,0,0)\r\n}\r\n```\r\nwould translate to\r\n```cs\r\npublic struct Color {\r\n\tpublic readonly static Color Blue = new Color(0, 0, 255);\r\n\tpublic readonly static Color Green = new Color(0, 255, 0);\r\n\tpublic readonly static Color Red = new Color(255, 0, 0);\r\n\t\r\n\tprivate Color(int R, int G, int B) {\r\n\t    this.R = R;\r\n\t    this.G = G;\r\n\t    this.B = B;\r\n\t}\r\n\r\n\tpublic int R { get; }\r\n\tpublic int G { get; }\r\n\tpublic int B { get; }\r\n}\r\n```\r\nAnother example from Java docs:\r\n```cs\r\npublic enum struct Planet(double Mass, double Radius) {\r\n    Mercury (3.303e+23, 2.4397e6),\r\n    Venus   (4.869e+24, 6.0518e6),\r\n    Earth   (5.976e+24, 6.37814e6),\r\n    Mars    (6.421e+23, 3.3972e6),\r\n    Jupiter (1.9e+27,   7.1492e7),\r\n    Saturn  (5.688e+26, 6.0268e7),\r\n    Uranus  (8.686e+25, 2.5559e7),\r\n    Neptune (1.024e+26, 2.4746e7),\r\n    Pluto   (1.27e+22,  1.137e6);\r\n   \r\n    public const double G = 6.67300E-11;\r\n\r\n    public double SurfaceGravity =>\r\n        G * Mass / (Radius * Radius);\r\n    \r\n    public double SurfaceWeight(double otherMass) =>\r\n        otherMass * SurfaceGravity;\r\n}\r\n```\r\n\r\nThis struct must not be instantiable, because of the completeness of the pattern.\r\n\r\n### Enum classes\r\n\r\n*Enum classes* are useful for declaring **flat** hierarchy of ADTs (similar to F# discriminated unions). For example. the following\r\n```cs\r\npublic sealed abstract class Option<T> {\r\n\tpublic sealed class Some(T Value) : Option<T>;\r\n\tpublic sealed class None() : Option<T>;\r\n}\r\n```\r\ncould be written as\r\n```cs\r\npublic enum class Option<T> {\r\n\tSome(T value : Value),\r\n\tNone;\r\n}\r\n```\r\nWith enum classes, `abstract sealed` would be considered as an advanced feature where you can declare more complicated ADTs.\r\n\r\n#### Remarks\r\n- Each member translates to a subclass of the `Option<T>` in this example.\r\n- Enum classes can not have defined *record-parameter-list* in the root class.\r\n- Enum classes are implicitly `abstract sealed` and cannot extend any other types.\r\n- Enum class members can have a body to potentially override methods on the base (like Java).\r\n\r\n```cs\r\npublic enum class Expr {\r\n  Const(double Value)        { public override string ToString() => Value.ToString(); },\r\n  Mul(Expr Left, Expr Right) { public override string ToString() => $\"({Left} * {Right})\"; },\r\n  Add(Expr Left, Expr Right) { public override string ToString() => $\"({Left} + {Right})\"; },\r\n  Div(Expr Left, Expr Right) { public override string ToString() => $\"({Left} / {Right})\"; },\r\n  Sub(Expr Left, Expr Right) { public override string ToString() => $\"({Left} - {Right})\"; },\r\n}\r\n```\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/157229286","html_url":"https://github.com/dotnet/roslyn/issues/6739#issuecomment-157229286","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/6739","id":157229286,"user":{"login":"HaloFour","id":10102290,"avatar_url":"https://avatars.githubusercontent.com/u/10102290?v=3","gravatar_id":"","url":"https://api.github.com/users/HaloFour","html_url":"https://github.com/HaloFour","followers_url":"https://api.github.com/users/HaloFour/followers","following_url":"https://api.github.com/users/HaloFour/following{/other_user}","gists_url":"https://api.github.com/users/HaloFour/gists{/gist_id}","starred_url":"https://api.github.com/users/HaloFour/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HaloFour/subscriptions","organizations_url":"https://api.github.com/users/HaloFour/orgs","repos_url":"https://api.github.com/users/HaloFour/repos","events_url":"https://api.github.com/users/HaloFour/events{/privacy}","received_events_url":"https://api.github.com/users/HaloFour/received_events","type":"User","site_admin":false},"created_at":"2015-11-17T01:21:07Z","updated_at":"2015-11-17T01:21:07Z","body":"@gafter \r\n\r\nSure, I understand that `Option<T>` is only serving as an example of ADTs.\r\n\r\nI always thought that a `Some` of `null` in a functional language was one of those anomalies generally resulting from poor interop with non-functional languages or other hacky stuff.  I don't think I've ever seen any Scala of F# code written to defend against `Some` being `null`.  And if `None`/`Some` were in consideration for C# (and I mentioned that seems redundant given type patterns) I think I'd prefer to see them designed in such a way to be compatible with existing reference/nullable types, implemented as custom `is` operators.\r\n\r\nAnyway that's all a tangent to the proposal of using `enum`-like syntax to describe ADTs."}}