MonadLINQ

CSharp · Console

/Program.cs

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

class LazyList<T>
{
    private readonly IEnumerable<T> _enumerable;

    public LazyList(IEnumerable<T> enumerable)
    {
        _enumerable = enumerable;
    }

    public LazyList<TOut> Bind<TOut>(Func<T, LazyList<TOut>> f)
    {
        return new LazyList<TOut>(_enumerable.SelectMany(x => f(x)._enumerable));
    }

    public LazyList<T> Where(Func<T, bool> predicate)
    {
        return new LazyList<T>(_enumerable.Where(predicate));
    }

    public LazyList<TOut> Select<TOut>(Func<T, TOut> f)
    {
        return new LazyList<TOut>(_enumerable.Select(f));
    }

    public LazyList<TOut> SelectMany<TOut>(Func<T, LazyList<TOut>> f)
    {
        return Bind(f);
    }

    public LazyList<TJoin> SelectMany<TMid, TJoin>(
        Func<T, LazyList<TMid>> bind,
        Func<T, TMid, TJoin> project)
    {
        return new LazyList<TJoin>(
            _enumerable.SelectMany(
                x => bind(x)._enumerable.Select(y => project(x, y))
            )
        );
    }

    public static LazyList<T> Return(T value)
    {
        return new LazyList<T>(new[] { value });
    }

    public IEnumerable<T> AsEnumerable()
    {
        return _enumerable;
    }
}

class Program
{
    static LazyList<int> Choices(params int[] items)
    {
        return new LazyList<int>(items);
    }

    static LazyList<(int x, int y, int z)> Backtrack()
    {
        return
            from x in Choices(1, 2, 3, 4, 5)
            from y in Choices(1, 2, 3, 4, 5)
            from z in Choices(1, 2, 3, 4, 5)
            where x + y + z == 7
            select (x, y, z);
    }

    static void Main()
    {
        foreach (var result in Backtrack().AsEnumerable())
        {
            Console.WriteLine($"{result.x}, {result.y}, {result.z}");
        }
    }
}
;