{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/corefx/issues/18159","repository_url":"https://api.github.com/repos/dotnet/corefx","labels_url":"https://api.github.com/repos/dotnet/corefx/issues/18159/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/corefx/issues/18159/comments","events_url":"https://api.github.com/repos/dotnet/corefx/issues/18159/events","html_url":"https://github.com/dotnet/corefx/issues/18159","id":220670310,"number":18159,"title":"Option<T>/Maybe<T> and Either<TLeft, TRight>","user":{"login":"ElemarJR","id":105970,"avatar_url":"https://avatars1.githubusercontent.com/u/105970?v=3","gravatar_id":"","url":"https://api.github.com/users/ElemarJR","html_url":"https://github.com/ElemarJR","followers_url":"https://api.github.com/users/ElemarJR/followers","following_url":"https://api.github.com/users/ElemarJR/following{/other_user}","gists_url":"https://api.github.com/users/ElemarJR/gists{/gist_id}","starred_url":"https://api.github.com/users/ElemarJR/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ElemarJR/subscriptions","organizations_url":"https://api.github.com/users/ElemarJR/orgs","repos_url":"https://api.github.com/users/ElemarJR/repos","events_url":"https://api.github.com/users/ElemarJR/events{/privacy}","received_events_url":"https://api.github.com/users/ElemarJR/received_events","type":"User","site_admin":false},"labels":[{"id":153714228,"url":"https://api.github.com/repos/dotnet/corefx/labels/api-needs-work","name":"api-needs-work","color":"207de5","default":false},{"id":174276033,"url":"https://api.github.com/repos/dotnet/corefx/labels/area-System.Runtime","name":"area-System.Runtime","color":"d4c5f9","default":false},{"id":206504884,"url":"https://api.github.com/repos/dotnet/corefx/labels/Design%20Discussion","name":"Design Discussion","color":"5319e7","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/dotnet/corefx/milestones/5","html_url":"https://github.com/dotnet/corefx/milestone/5","labels_url":"https://api.github.com/repos/dotnet/corefx/milestones/5/labels","id":1328080,"number":5,"title":"Future","description":"Milestone tracking the issues triaged for an unspecified future release","creator":{"login":"joshfree","id":1302850,"avatar_url":"https://avatars2.githubusercontent.com/u/1302850?v=3","gravatar_id":"","url":"https://api.github.com/users/joshfree","html_url":"https://github.com/joshfree","followers_url":"https://api.github.com/users/joshfree/followers","following_url":"https://api.github.com/users/joshfree/following{/other_user}","gists_url":"https://api.github.com/users/joshfree/gists{/gist_id}","starred_url":"https://api.github.com/users/joshfree/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joshfree/subscriptions","organizations_url":"https://api.github.com/users/joshfree/orgs","repos_url":"https://api.github.com/users/joshfree/repos","events_url":"https://api.github.com/users/joshfree/events{/privacy}","received_events_url":"https://api.github.com/users/joshfree/received_events","type":"User","site_admin":false},"open_issues":1068,"closed_issues":90,"state":"open","created_at":"2015-09-29T00:25:45Z","updated_at":"2017-04-24T20:20:29Z","due_on":null,"closed_at":null},"comments":42,"created_at":"2017-04-10T14:52:15Z","updated_at":"2017-04-24T20:46:00Z","closed_at":null,"body":"```csharp\r\npublic Option<Employee> GetById(string id)\r\n    => new DbContext().Find(id);\r\n```\r\n\r\ninstead of \r\n\r\n```csharp\r\npublic Employee GetById(string id)\r\n    => new DbContext().Find(id);\r\n```\r\n\r\nThe proposed method signature reveals much better the real intent of this method/function. Right?\r\n\r\n`Option<T>` could provide a `Match` function....\r\n\r\nHere is a very basic implementation:\r\n\r\n```csharp\r\nnamespace ElemarJR.FunctionalCSharp\r\n{\r\n    using static Helpers;\r\n\r\n    public struct Option<T>\r\n    {\r\n        internal T Value { get; }\r\n        public bool IsSome { get; }\r\n        public bool IsNone => !IsSome;\r\n\r\n        internal Option(T value, bool isSome)\r\n        {\r\n            Value = value;\r\n            IsSome = isSome;\r\n        }\r\n\r\n        public TR Match<TR>(Func<T, TR> some, Func<TR> none)\r\n            => IsSome ? some(Value) : none();\r\n\r\n        public Unit Match(Action<T> some, Action none)\r\n            => Match(ToFunc(some), ToFunc(none));\r\n\r\n        public static readonly Option<T> None = new Option<T>();\r\n\r\n        public static implicit operator Option<T>(T value)\r\n            => Some(value);\r\n\r\n        public static implicit operator Option<T>(NoneType _)\r\n            => None;\r\n    }\r\n}\r\n```\r\n\r\nwith some additional operators:\r\n\r\n```csharp\r\nnamespace ElemarJR.FunctionalCSharp\r\n{\r\n    using static Helpers;\r\n\r\n    public static class Option\r\n    {\r\n        #region Of\r\n        public static Option<T> Of<T>(T value)\r\n            => new Option<T>(value, value != null);\r\n        #endregion\r\n\r\n        #region Apply\r\n        public static Option<TResult> Apply<T, TResult>\r\n            (this Option<Func<T, TResult>> @this, Option<T> arg)\r\n            => @this.Bind(f => arg.Map(f));\r\n\r\n        public static Option<Func<TB, TResult>> Apply<TA, TB, TResult>\r\n             (this Option<Func<TA, TB, TResult>> @this, Option<TA> arg)\r\n             => Apply(@this.Map(Helpers.Curry), arg);\r\n        #endregion\r\n\r\n        #region Map\r\n        public static Option<TR> Map<T, TR>(\r\n            this Option<T> @this,\r\n            Func<T, TR> mapfunc\r\n            ) =>\r\n                @this.IsSome\r\n                    ? Some(mapfunc(@this.Value))\r\n                    : None;\r\n\r\n        public static Option<Func<TB, TResult>> Map<TA, TB, TResult>(\r\n            this Option<TA> @this,\r\n            Func<TA, TB, TResult> func\r\n        ) => @this.Map(func.Curry());\r\n        #endregion\r\n\r\n        #region Bind\r\n        public static Option<TR> Bind<T, TR>(\r\n                this Option<T> @this,\r\n                Func<T, Option<TR>> bindfunc\r\n            ) =>\r\n            @this.IsSome\r\n                ? bindfunc(@this.Value)\r\n                : None;\r\n        #endregion\r\n\r\n        #region GetOrElse\r\n        public static T GetOrElse<T>(\r\n            this Option<T> @this,\r\n            Func<T> fallback\r\n            ) =>\r\n                @this.Match(\r\n                    some: value => value,\r\n                    none: fallback\r\n                    );\r\n\r\n        public static T GetOrElse<T>(\r\n            this Option<T> @this,\r\n            T @else\r\n            ) =>\r\n                GetOrElse(@this, () => @else);\r\n        #endregion\r\n\r\n        #region OrElse\r\n        public static Option<T> OrElse<T>(\r\n            this Option<T> @this,\r\n            Option<T> @else\r\n        ) => @this.Match(\r\n            some: _ => @this,\r\n            none: () => @else\r\n        );\r\n\r\n\r\n        public static Option<T> OrElse<T>(\r\n            this Option<T> @this,\r\n            Func<Option<T>> fallback\r\n        ) => @this.Match(\r\n            some: _ => @this,\r\n            none: fallback\r\n        );\r\n        #endregion\r\n    }\r\n}\r\n```\r\n\r\nand some LINQ support:\r\n\r\n```csharp\r\nnamespace System.Linq\r\n{\r\n    using static Helpers;\r\n    public static partial class LinqExtensions\r\n    {\r\n        public static Option<TResult> Select<T, TResult>(\r\n                this Option<T> @this,\r\n                Func<T, TResult> func)\r\n            => @this.Map(func);\r\n\r\n        public static Option<TResult> SelectMany<T, TB, TResult>(\r\n            this Option<T> @this,\r\n            Func<T, Option<TB>> binder,\r\n            Func<T, TB, TResult> projector\r\n        ) => @this.Match(\r\n            none: () => None,\r\n            some: (t) => @this.Bind(binder).Match(\r\n                none: () => None,\r\n                some: (tb) => Some(projector(t, tb))\r\n            )\r\n        );\r\n\r\n        public static Option<T> Where<T>(\r\n            this Option<T> option,\r\n            Func<T, bool> predicate\r\n        ) => option.Match(\r\n            none: () => None,\r\n            some: o => predicate(o) ? option : None\r\n        );\r\n    }\r\n}\r\n```\r\n\r\nThis proposal does not incur any CLR changes. \r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/corefx/issues/comments/296817137","html_url":"https://github.com/dotnet/corefx/issues/18159#issuecomment-296817137","issue_url":"https://api.github.com/repos/dotnet/corefx/issues/18159","id":296817137,"user":{"login":"DavidArno","id":196899,"avatar_url":"https://avatars0.githubusercontent.com/u/196899?v=3","gravatar_id":"","url":"https://api.github.com/users/DavidArno","html_url":"https://github.com/DavidArno","followers_url":"https://api.github.com/users/DavidArno/followers","following_url":"https://api.github.com/users/DavidArno/following{/other_user}","gists_url":"https://api.github.com/users/DavidArno/gists{/gist_id}","starred_url":"https://api.github.com/users/DavidArno/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DavidArno/subscriptions","organizations_url":"https://api.github.com/users/DavidArno/orgs","repos_url":"https://api.github.com/users/DavidArno/repos","events_url":"https://api.github.com/users/DavidArno/events{/privacy}","received_events_url":"https://api.github.com/users/DavidArno/received_events","type":"User","site_admin":false},"created_at":"2017-04-24T20:46:00Z","updated_at":"2017-04-24T20:46:00Z","body":"@svick,\r\n\r\n> So, what I understand: `Option<T>` would not end the nightmare, non-nullable reference types probably will.\r\n\r\nSeriously? Have you seen how often folk use `T?` to enable their structs to be `null`? Whilst better coders will enjoy the benefits non-nullable ref types, the vast majority of devs will just spread even more `T?` throughout their code..."}}
{"actor":{"display_login":"DavidArno"}}