using System.Collections.Generic;
public static void Main()
var range = Enumerable.Range(1, 10);
Console.WriteLine(MapAnyFunctorEnumerable(range, x => x).SequenceEqual(range));
int? nullableNull = null;
Console.WriteLine(MapAnyFunctorNullable(nullableTen, x => x) == nullableTen);
Console.WriteLine(MapAnyFunctorNullable(nullableNull, x => x) == nullableNull);
static IEnumerable<B> MapAnyFunctorEnumerable<A, B>(IEnumerable<A> source, Func<A, B> map) =>
EnumerableApplicative.LiftA2(source, EnumerableApplicative.Pure(0), (a, _) => map(a));
static B? MapAnyFunctorNullable<A, B>(A? source, Func<A, B> map) where A : struct where B : struct =>
NullableApplicative.LiftA2(source, NullableApplicative.Pure(0), (a, _) => map(a));
public static class EnumerableApplicative
public static IEnumerable<A> Pure<A>(A a) => new[] { a };
public static IEnumerable<C> LiftA2<A, B, C>(IEnumerable<A> ta, IEnumerable<B> tb, Func<A, B, C> map2) =>
ta.SelectMany(a => tb.Select(b => map2(a, b)));
public static class NullableApplicative
public static A? Pure<A>(A a) where A : struct => a;
public static C? LiftA2<A, B, C>(A? ta, B? tb, Func<A, B, C> map2) where A : struct where B : struct where C : struct =>
(A a, B b) => map2(a, b),