Created
March 19, 2018 16:08
-
-
Save benjamin-hodgson/8c7ddf2356509a0177394e81384ddfec to your computer and use it in GitHub Desktop.
Composable lens hierarchy using default interface implementations
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
interface ISetter<in S, out T, out A, in B> | |
{ | |
T Rewrite(S oldContainer, Func<A, B> rewriter); | |
} | |
interface IFold<in S, out A> | |
{ | |
R Aggregate<R>(S container, R seed, Func<R, A, R> aggregator); | |
} | |
interface ITraversal<in S, out T, out A, in B> : ISetter<S, T, A, B>, IFold<S, A> | |
{ | |
T SetList(S oldContainer, IEnumerable<B> newChildren); | |
T Rewrite(S oldContainer, Func<A, B> rewriter) | |
=> SetList(oldContainer, this.GetList(container).Select(rewriter)); | |
} | |
interface IGetter<in S, out A> : IFold<S, A> | |
{ | |
A Get(S container); | |
R Aggregate<R>(S container, R seed, Func<R, A, R> aggregator) | |
=> aggregator(seed, Get(container)); | |
} | |
interface ILens<in S, out T, out A, in B> : ITraversal<S, T, A, B>, IGetter<S, A> | |
{ | |
T Set(S oldContainer, B newValue); | |
T SetList(S oldContainer, IEnumerable<B> newChildren) | |
=> Set(oldContainer, newChildren.Single()); | |
} | |
interface IReview<out T, in B> | |
{ | |
T Inject(B value); | |
} | |
interface IPrism<in S, out T, out A, in B> : IReview<T, B>, ITraversal<S, T, A, B> | |
{ | |
IEither<T, A> TryGet(S value); | |
R Aggregate<R>(S container, R seed, Func<R, A, R> aggregator) | |
{ | |
var result = TryGet(container); | |
if (result.IsLeft) | |
{ | |
return seed; | |
} | |
return aggregator(seed, result.Right); | |
} | |
T SetList(S oldContainer, IEnumerable<B> newChildren) | |
=> Inject(newChildren.Single()); | |
} | |
interface IEither<out T, out U> | |
{ | |
R Match<R>(Func<T, R> ifLeft, Func<U, R> ifRight); | |
} | |
static class Lens | |
{ | |
public static ILens<S, T, U, V> _(this ILens<S, T, A, B> lens1, ILens<A, B, U, V> lens2); | |
public static ITraversal<S, T, U, V> _(this ITraversal<S, T, A, B> traversal1, ITraversal<A, B, U, V> traversal2); | |
public static IGetter<S, U> _(this IGetter<S, A> getter1, IGetter<A, U> getter2); | |
public static ISetter<S, T, U, V> _(this ISetter<S, T, A, B> setter1, ISetter<A, B, U, V> setter2); | |
public static IFold<S, U> _(this IFold<S, A> fold1, IFold<A, U> fold2); | |
public static IPrism<S, T, U, V> _(this IPrism<S, T, A, B> prism1, this IPrism<A, B, U, V> prism2); | |
public static IReview<T, V> _(this IReview<T, B> review1, IReview<B, V> review2); | |
public static A Get<S, A>(this S container, IGetter<S, A> getter); | |
public static T Set<S, T, A, B>(this S container, ISetter<S, T, A, B> setter, B newValue); | |
public static ImmutableList<A> GetList<S, A>(this S container, IFold<S, A> fold); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment