.NET Fiddle

CSharp · Console

/Program.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        var eta = Enumerable.Range(3, 2);
        var etb = Enumerable.Range(15, 4);

        int? nta = 10;
        int? ntb = null;

        Print(EnumerableApplicative.LiftA2(eta, etb, (a, b) => (a, b)));  // Combine
        Print(NullableApplicative.LiftA2(nta, nta, (a, b) => (a, b)));  // Combine
        Print(NullableApplicative.LiftA2(nta, ntb, (a, b) => (a, b)));  // Combine
        Print(ZipListApplicative.LiftA2(new ZipList<int>(eta), new ZipList<int>(etb), (a, b) => (a, b)));  // Combine
    }

    private static void Print<T>(T value) where T : struct
    {
        Console.WriteLine(value);
    }

    private static void Print<T>(T? value) where T :struct
    {
        Console.WriteLine(value?.ToString() ?? "Null");
    }

    private static void Print<T>(IEnumerable<T> source)
    {
        Console.WriteLine($"[{string.Join(", ", source)}]");
    }
}

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 =>
        (ta, tb) switch
        {
            (A a, B b) => map2(a, b),
            _ => default(C?)
        };
}

public static class ZipListApplicative
{
    public static IEnumerable<A> Pure<A>(A a) =>
        Enumerable.Repeat(a, int.MaxValue); // вообще тут должен быть бесконечный генератор
    public static ZipList<C> LiftA2<A, B, C>(ZipList<A> ta, ZipList<B> tb, Func<A, B, C> map2) =>
        new ZipList<C>(ta.Zip(tb, map2));
}

public class ZipList<T> : IEnumerable<T>
{
    private readonly IEnumerable<T> _inner;

    public ZipList(IEnumerable<T> inner)
    {
        _inner = inner;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return _inner.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable)_inner).GetEnumerator();
    }
}
;