Created
February 8, 2019 10:07
-
-
Save mormegil-cz/f63ede60f7ffc7439330d5c1f3c81be6 to your computer and use it in GitHub Desktop.
Yoneda lemma examples implemented in C#
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
void Main() | |
{ | |
ToYoneda(new[] {1, 2, -3, 4}.ToFunctor()) | |
//.Alpha(x => x).Dump(); | |
.Alpha(x => (x >= 0 ? "+" : "-")).Dump(); | |
ToYoneda(new int?(3).ToFunctor()) | |
.Alpha(x => (x >= 0 ? "+" : "-")).Dump(); | |
FromYoneda(ToYoneda(new[] { 1, 2, -3, 4 }.ToFunctor())).Dump(); | |
} | |
/// Generic functor interface | |
public interface IFunctor<T> | |
{ | |
IFunctor<U> Select<U>(Func<T, U> f); | |
} | |
/// Representation using the function from Yoneda lemma | |
public interface IYonedaRepresentation<TElement> | |
{ | |
/// (a -> x) -> F x | |
IFunctor<T> Alpha<T>(Func<TElement, T> f); | |
} | |
/// Implementation of the F x ~~~> (a -> x) -> F x direction | |
public static IYonedaRepresentation<T> ToYoneda<T>(IFunctor<T> original) => new YonedaRepresentation<T>(original); | |
/// Implementation of the (a -> x) -> F x ~~~> F x direction | |
public static IFunctor<T> FromYoneda<T>(IYonedaRepresentation<T> yoneda) => yoneda.Alpha(x => x); | |
/// Implementation of the Yoneda representation | |
public class YonedaRepresentation<TElement> | |
: IYonedaRepresentation<TElement> | |
{ | |
private readonly IFunctor<TElement> original; | |
public YonedaRepresentation(IFunctor<TElement> original) | |
{ | |
this.original = original; | |
} | |
public IFunctor<T> Alpha<T>(Func<TElement, T> f) => original.Select(f); | |
} | |
/// Helper extesions to easily get functor interface for common functors | |
public static class FunctorExtensions | |
{ | |
public static MaybeFunctor<T> ToFunctor<T>(this T? nullable) where T : struct | |
=> MaybeFunctor<T>.FromNullable(nullable); | |
public static EnumerableFunctor<T> ToFunctor<T>(this IEnumerable<T> enumerable) => new EnumerableFunctor<T>(enumerable); | |
} | |
/// Implementation of the functor interface for the Maybe functor (nullable types) | |
public class MaybeFunctor<T> : IFunctor<T> | |
{ | |
public static readonly MaybeFunctor<T> Empty = new MaybeFunctor<T>(); | |
private readonly bool hasValue; | |
private readonly T value; | |
private MaybeFunctor() | |
{ | |
} | |
public MaybeFunctor(T value) | |
{ | |
this.hasValue = true; | |
this.value = value; | |
} | |
public static MaybeFunctor<U> FromNullable<U>(U? value) where U : struct | |
=> value.HasValue ? new MaybeFunctor<U>(value.GetValueOrDefault()) : MaybeFunctor<U>.Empty; | |
public IFunctor<U> Select<U>(Func<T, U> f) => hasValue ? new MaybeFunctor<U>(f(value)) : MaybeFunctor<U>.Empty; | |
private object ToDump() => new { hasValue, value }; | |
} | |
/// Implementation of the Functor interface for enumerables | |
public class EnumerableFunctor<T> : IFunctor<T> | |
{ | |
private readonly IEnumerable<T> list; | |
public EnumerableFunctor(IEnumerable<T> list) | |
{ | |
this.list = list; | |
} | |
public IFunctor<U> Select<U>(Func<T, U> f) => new EnumerableFunctor<U>(list.Select(f)); | |
private object ToDump() => list; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment