Skip to content

Instantly share code, notes, and snippets.

@kiwidev
Forked from theunrepentantgeek/immutable.cs
Last active February 9, 2016 04:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kiwidev/2806a6b67ca2b29c2198 to your computer and use it in GitHub Desktop.
Save kiwidev/2806a6b67ca2b29c2198 to your computer and use it in GitHub Desktop.
using System;
namespace Immutable
{
enum Qux { Qux1, Qux2 }
static class Option
{
public static Option<T> Value<T>(T value)
{
return new Option<T>(value);
}
}
struct Option<T>
{
public static readonly Option<T> None = new Option();
private readonly bool _hasValue;
private readonly T _value;
public Option(T value)
{
_hasValue = true;
_value = value;
}
public T Value
{
get { return _value; }
}
public bool HasValue
{
get { return _hasValue; }
}
public T ValueOrDefault(T defaultValue)
{
return _hasValue ? _value : defaultValue;
}
}
class Baz
{
public Baz(Qux qux)
{
Qux = qux;
}
public Qux Qux { get; }
}
class Bar
{
public Bar(Baz baz)
{
Baz = baz;
}
public Baz Baz { get; }
}
class Foo
{
public Foo(Bar bar)
{
Bar = bar;
}
public Bar Bar { get; }
}
static class Extensions
{
public static Foo With(this Foo foo, Option<Bar> bar = default(Option<Bar>)) => new Foo(bar.ValueOrDefault(foo.Bar));
public static Bar With(this Bar bar, Option<Bar> baz = default(Option<Baz>)) => new Bar(baz.ValueOrDefault(bar.Baz));
public static Baz With(this Baz baz, Option<Qux> qux = default(Option<Qux>)) => new Baz(qux.ValueOrDefault(baz.Qux));
public static Foo With(this Foo foo, Func<Bar, Bar> bar = null) => new Foo(bar != null ? bar(foo.Bar) : foo.Bar);
public static Bar With(this Bar bar, Func<Baz, Baz> baz = null) => new Bar(baz != null ? baz(foo.Baz) : bar.Baz);
public static Baz With(this Baz baz, Func<Qux, Qux> qux = null) => new Baz(qux != null ? qux(foo.Qux) : baz.Qux);
}
static class Program
{
private static Foo SetQux(Foo foo, Qux qux) => foo.With(Option.Value(foo.Bar.With(Option.Value(foo.Bar.Baz.With(Option.Value(qux))))));
private static Foo SetQuxAlternate(Foo foo, Qux qux) => foo.With(bar => bar.With(baz => baz.With(Option.Value(qux)));
public static void Main()
{
var it = new Foo(new Bar(new Baz(Qux.Qux1)));
Console.WriteLine(it.Bar.Baz.Qux);
var newIt = SetQux(it, Qux.Qux2);
Console.WriteLine(newIt.Bar.Baz.Qux);
var newIt2 = SetQuxAlternate(it, Qux.Qux2);
Console.WriteLine(newIt.Bar.Baz.Qux);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment