Created
August 3, 2012 07:04
-
-
Save dtchepak/3245278 to your computer and use it in GitHub Desktop.
Attempt at lens in c#
This file contains hidden or 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
public class Lens<T, TValue> | |
{ | |
public Func<T, TValue> Get { get; private set; } | |
public Func<TValue, T, T> Set { get; private set; } | |
public Lens(Func<T, TValue> get, Func<TValue, T, T> set) | |
{ | |
Get = get; | |
Set = set; | |
} | |
public T Modify(Func<TValue, TValue> updateValue, T original) | |
{ | |
var newValue = updateValue(Get(original)); | |
return Set(newValue, original); | |
} | |
public Lens<T1, TValue> Compose<T1>(Lens<T1, T> lens) | |
{ | |
return new Lens<T1, TValue>( | |
t1 => Get(lens.Get(t1)), | |
(value, t1) => | |
{ | |
var t = lens.Get(t1); | |
return lens.Set(Set(value, t), t1); | |
} | |
); | |
} |
This file contains hidden or 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
public class Address | |
{ | |
public Address(int number, string street, State state) { Number = number; Street = street; State = state; } | |
public int Number { get; private set; } | |
public string Street { get; private set; } | |
public State State { get; private set; } | |
} | |
public class State | |
{ | |
public State(string name) { Name = name; } | |
public string Name { get; private set; } | |
} | |
public readonly static Lens<State, string> StateNameLens | |
= new Lens<State, string>(x => x.Name, (value, x) => new State(value)); | |
public readonly static Lens<Address, int> AddressNumberLens | |
= new Lens<Address, int>(x => x.Number, (value, x) => new Address(value, x.Street, x.State)); | |
public readonly static Lens<Address, string> AddressStreetLens | |
= new Lens<Address, string>(x => x.Street, (value, x) => new Address(x.Number, value, x.State)); | |
public readonly static Lens<Address, State> AddressStateLens | |
= new Lens<Address, State>(x => x.State, (value, x) => new Address(x.Number, x.Street, value)); | |
[Test] | |
public void UpdateOneProperty() | |
{ | |
var state = new State("NSW"); | |
var result = StateNameLens.Modify(x => "VIC", state); | |
result.Name.ShouldBe("VIC"); | |
} | |
[Test] | |
public void ComposeUpdate() | |
{ | |
var address = new Address(1, "First St", new State("NSW")); | |
var addressStateLens = StateNameLens.Compose(AddressStateLens); | |
var updatedAddress = addressStateLens.Set("VIC", address); | |
updatedAddress.Number.ShouldBe(address.Number); | |
updatedAddress.Street.ShouldBe(address.Street); | |
updatedAddress.State.Name.ShouldBe("VIC"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment