Last active
March 20, 2022 23:01
-
-
Save andrewstellman/60337be77ff19201090c22e2e202dca3 to your computer and use it in GitHub Desktop.
Example of a toy Option<T> class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace Toy_Option | |
{ | |
public abstract class Option<T> : IEnumerable<T> | |
{ | |
public abstract IEnumerator<T> GetEnumerator(); | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
throw new NotImplementedException(); | |
} | |
public abstract T GetOrElse(T orElse); | |
public static Option<T> None => new None<T>(); | |
public static Option<T> FromEnumerable(IEnumerable<T> input) | |
{ | |
if (input == null) return Option<T>.None as Option<T>; | |
if (input.Count() == 0) return Option<T>.None as Option<T>; | |
return new Some<T>(input.First()); | |
} | |
public bool IsDefined | |
{ | |
get | |
{ | |
if (this is None<T>) return false; | |
return (this.Count() > 0); | |
} | |
} | |
public bool IsEmpty | |
{ | |
get { return !IsDefined; } | |
} | |
} | |
public class Some<T> : Option<T>, IEquatable<Some<T>> | |
{ | |
private readonly List<T> _list = new List<T>(); | |
public override T GetOrElse(T orElse) => _list.Count == 0 ? orElse : _list[0]; | |
public Some(T value) => _list.Add(value); | |
// implement IEnumerable<T> | |
public override IEnumerator<T> GetEnumerator() => _list.GetEnumerator(); | |
public override bool Equals(object obj) | |
{ | |
return Equals(obj as Some<T>); | |
} | |
// implement IEquatable<Some<T>> | |
public bool Equals(Some<T> other) | |
{ | |
return other != null && | |
EqualityComparer<List<T>>.Default.Equals(_list, other._list); | |
} | |
public override int GetHashCode() | |
{ | |
return -595181494 + EqualityComparer<List<T>>.Default.GetHashCode(_list); | |
} | |
public static bool operator ==(Some<T> left, Some<T> right) | |
{ | |
return EqualityComparer<Some<T>>.Default.Equals(left, right); | |
} | |
public static bool operator !=(Some<T> left, Some<T> right) | |
{ | |
return !(left == right); | |
} | |
} | |
public class None<T> : Option<T>, IEquatable<None<T>> | |
{ | |
private readonly List<T> _list = new List<T>(); | |
public override T GetOrElse(T orElse) => orElse; | |
// implement IEnumerable<T> | |
public override IEnumerator<T> GetEnumerator() => _list.GetEnumerator(); | |
// implement IEquatable<None<T> | |
public override bool Equals(object obj) | |
{ | |
return Equals(obj as None<T>); | |
} | |
public bool Equals(None<T> other) | |
{ | |
return other != null && | |
EqualityComparer<List<T>>.Default.Equals(_list, other._list); | |
} | |
public override int GetHashCode() | |
{ | |
return -595181494 + EqualityComparer<List<T>>.Default.GetHashCode(_list); | |
} | |
public static bool operator ==(None<T> left, None<T> right) | |
{ | |
return EqualityComparer<None<T>>.Default.Equals(left, right); | |
} | |
public static bool operator !=(None<T> left, None<T> right) | |
{ | |
return !(left == right); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace Toy_Option | |
{ | |
class MainClass | |
{ | |
public static void Main(string[] args) | |
{ | |
Option<int> n = Option<int>.None; | |
Console.WriteLine(n.Select(e => $"It's {e}")); | |
var a = new Some<int>(1); | |
IEnumerable<string> q = a.Select(e => $"It's {e}"); | |
foreach (var s in q) | |
{ | |
Console.WriteLine(s); | |
} | |
var b = new Some<int>(2); | |
IEnumerable<int> r = b.Concat(Option<int>.None).Concat(a); | |
Option<int> o = Option<int>.FromEnumerable(r); | |
Console.WriteLine(o.GetOrElse(3)); | |
Console.WriteLine($"{a.IsDefined}, {a.IsEmpty}"); | |
Console.WriteLine($"{b.IsDefined}, {b.IsEmpty}"); | |
Console.WriteLine($"{n.IsDefined}, {n.IsEmpty}"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment