C#: Interface

Interface

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Monad;
using System.Collections;

namespace Monad
{
    class Program
    {
        static void Main(string[] args)
        {
            var result = GenericAdd<int, int, Maybe<int>, Maybe<int>>(Maybe<int>.Nothing, 2.ToMaybe());

            if (result.HasValue)
                Console.WriteLine(result);
            else
                Console.WriteLine("Nothing");

            var a = TMonad<MyList<int>, MyList<Tuple<int, int>>, int, Tuple<int, int>>.Bind;
            a = TMonad<MyList<int>, MyList<Tuple<int, int>>, int, Tuple<int, int>>.Bind;
            var result2 = GenericAdd<int, Tuple<int, int>, MyList<int>, MyList<Tuple<int, int>>>(new MyList<int> { 1, 2, 3 }, new MyList<int> { 4, 5, 6 });

            foreach (var item in result2)
            {
                Console.WriteLine(item);
            }
            Console.ReadLine();
        }

        private static CB GenericAdd<A, B, CA, CB>(CA ai, CA bi)
            where CA : IGeneric<A>
            where CB : IGeneric<B>
        {
            var result = TMonad<CA, CB, A, B>.Bind(ai, a =>
            {
                return TMonad<CA, CB, A, B>.Bind(bi, b =>
                {
                    return TMonad<CB, CB, B, B>.Return(TAdder<A, B>.Add(a, b));
                });
            });
            return result;
        }
    }

    public interface IGeneric<T> { }

    public class TMonad<CA, CB, A, B>
        where CA : IGeneric<A>
        where CB : IGeneric<B>
    {
        public static Func<CA, Func<A, CB>, CB> Bind;
        public static Func<A, CA> Return;

        static TMonad()
        {
            TMonad<Maybe<A>, Maybe<B>, A, B>.Bind = MaybeMonad<A, B>.Bind;
            TMonad<Maybe<A>, Maybe<B>, A, B>.Return = MaybeMonad<A, B>.Return;

            TMonad<MyList<A>, MyList<B>, A, B>.Bind = ListMonad<A, B>.Bind;
            TMonad<MyList<A>, MyList<B>, A, B>.Return = ListMonad<A, B>.Return;
        }
    }

    public class TAdder<A, B>
    {
        public static Func<A, A, B> Add;

        static TAdder()
        {
            TAdder<int, int>.Add = (x, y) => x + y;
            TAdder<String, string>.Add = (x, y) => x + y;
            TAdder<int, Tuple<int, int>>.Add = (x, y) => new Tuple<int, int>(x, y);
        }
    }

    public class MyList<T> : List<T>, IGeneric<T>
    {
        public MyList()
        {}

        public MyList(List<T> l)
        {
            this.AddRange(l);
        }
    }

    public class Maybe<T> : IGeneric<T>
    {
        public readonly static Maybe<T> Nothing = new Maybe<T>();
        public T Value { get; private set; }
        public bool HasValue { get; private set; }

        Maybe()
        {
            HasValue = false;
        }
        public Maybe(T value)
        {
            Value = value;
            HasValue = true;
        }
    }

    public class MaybeMonad<A, B>
    {
        public static Maybe<B> Bind(Maybe<A> a, Func<A, Maybe<B>> f)
        {
            if (a.HasValue) return f(a.Value);
            else return Maybe<B>.Nothing;
        }

        public static Maybe<A> Return(A a)
        {
            return a.ToMaybe();
        }
    }

    public class ListMonad<A, B>
    {
        public static MyList<B> Bind(MyList<A> a, Func<A, MyList<B>> f)
        {
            return new MyList<B>(a.SelectMany(x => f(x)).ToList());
        }

        public static MyList<A> Return(A a)
        {
            return new MyList<A> { a };
        }
    }

    public static class Helpers
    {
        public static Maybe<T> ToMaybe<T>(this T value)
        {
            return new Maybe<T>(value);
        }
    }
}

interface

Leave a comment

Leave a Reply