Skip to content

Instantly share code, notes, and snippets.

@AlexeyRaga
Created August 17, 2022 01:27
Show Gist options
  • Save AlexeyRaga/502aec50fa89b08ca7f47a320da1f5e7 to your computer and use it in GitHub Desktop.
Save AlexeyRaga/502aec50fa89b08ca7f47a320da1f5e7 to your computer and use it in GitHub Desktop.
LINQ for Option
namespace CSharpTests;
// I know this is ugly and bad encoding of Option
// but it's OK for this demo
public interface Option<T> {}
public record None<T>() : Option<T>;
public record Some<T>(T Value) : Option<T>;
// let's make LINQ work
public static class EnvelopeExtensions
{
public static Option<R> Select<T, R>(this Option<T> source, Func<T, R> mapper) =>
source switch
{
None<T> => new None<R>(),
Some<T> x => new Some<R>(mapper(x.Value)),
_ => throw new Exception("Impossible happened, panic")
};
public static Option<R> SelectMany<T, I, R>(this Option<T> source, Func<T, Option<I>> bind, Func<T, I, R> proj) =>
source switch
{
None<T> => new None<R>(),
Some<T> x => bind(x.Value).Select(a => proj(x.Value, a)),
_ => throw new Exception("Impossible happened, panic")
};
}
public class UnitTest1
{
[Fact]
public void Refl()
{
var someResult =
from x in new Some<bool>(false)
from y in new Some<bool>(true)
select (x, y);
var someExpected = new Some<(bool, bool)>((false, true));
someResult.Should().Be(someExpected);
var noneResult =
from x in new None<bool>()
from y in new Some<bool>(true)
select (x, y);
var noneExpected = new None<(bool, bool)>();
noneResult.Should().Be(noneExpected);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment