Skip to content

Instantly share code, notes, and snippets.

@andrewstellman
Last active March 20, 2022 23:01
Show Gist options
  • Save andrewstellman/60337be77ff19201090c22e2e202dca3 to your computer and use it in GitHub Desktop.
Save andrewstellman/60337be77ff19201090c22e2e202dca3 to your computer and use it in GitHub Desktop.
Example of a toy Option<T> class
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);
}
}
}
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