Created
September 30, 2011 19:17
-
-
Save hodzanassredin/1254715 to your computer and use it in GitHub Desktop.
secont implementation of monad
This file contains hidden or 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
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Text; | |
| using System.IO; | |
| using Monad; | |
| namespace Monad | |
| { | |
| public interface Polymorph<T> | |
| { | |
| } | |
| public interface IMonad | |
| { | |
| Polymorph<B> Bind<A, B>(Polymorph<A> a, Func<A, Polymorph<B>> f); | |
| Polymorph<A> Return<A>(A a); | |
| } | |
| public class MyList<T> : List<T>, Polymorph<T> | |
| { | |
| public MyList() | |
| { | |
| } | |
| public MyList(List<T> from) | |
| { | |
| this.AddRange(from); | |
| } | |
| } | |
| public class ListMonad : IMonad | |
| { | |
| public Polymorph<B> Bind<A, B>(Polymorph<A> a, Func<A, Polymorph<B>> f) | |
| { | |
| var res = new MyList<B>(); | |
| foreach (var item in (a as MyList<A>)) | |
| { | |
| try | |
| { | |
| res.AddRange(f(item) as MyList<B>); | |
| } | |
| catch { } | |
| } | |
| return res; | |
| } | |
| public Polymorph<A> Return<A>(A a) | |
| { | |
| var res = new MyList<A>(); | |
| res.Add(a); | |
| return res; | |
| } | |
| } | |
| class Program | |
| { | |
| static void Main(string[] args) | |
| { | |
| var result = new ListMonad() | |
| .ReturnStart("c:\\") | |
| .Do(x => Directory.GetDirectories(x).ToML()) | |
| .Do(x => Directory.GetDirectories(x).ToML()) | |
| .Do(x => Directory.GetDirectories(x).Select(y=>y.Length).ToML()) | |
| .DoReturn<int, int, MyList<int>>(x=>x.Sum())//this one | |
| .Finish<int, MyList<int>>();// and this one херня потомучто голова уже болит думать как грамотно сделать кастование | |
| foreach (var item in result) | |
| { | |
| Console.WriteLine(item); | |
| } | |
| Console.ReadLine(); | |
| } | |
| } | |
| public static class Exts | |
| { | |
| public static MyList<T> ToML<T>(this IEnumerable<T> source) | |
| { | |
| return new MyList<T>(source.ToList()); | |
| } | |
| public static Tuple<Polymorph<A>, IMonad> ReturnStart<A>(this IMonad monad, A init) | |
| { | |
| return new Tuple<Polymorph<A>, IMonad>(monad.Return(init), monad); | |
| } | |
| public static Tuple<Polymorph<A>, IMonad> Start<ACONT, A, B>(this IMonad monad, Polymorph<A> init) | |
| { | |
| return new Tuple<Polymorph<A>, IMonad>(init, monad); | |
| } | |
| public static P Finish<A, P>(this Tuple<Polymorph<A>, IMonad> prev) | |
| where P : class, Polymorph<A> | |
| { | |
| return prev.Item1 as P; | |
| } | |
| public static Tuple<Polymorph<B>, IMonad> Do<A, B>(this Tuple<Polymorph<A>, IMonad> prev, Func<A, Polymorph<B>> f) | |
| { | |
| return new Tuple<Polymorph<B>, IMonad>(prev.Item2.Bind(prev.Item1, f), prev.Item2); | |
| } | |
| public static Tuple<Polymorph<B>, IMonad> DoReturn<A, B, P>(this Tuple<Polymorph<A>, IMonad> prev, Func<P, B> f) | |
| where P : class, Polymorph<A> | |
| { | |
| return new Tuple<Polymorph<B>, IMonad>(prev.Item2.Return(f(prev.Item1 as P)), prev.Item2); | |
| } | |
| public static Tuple<Polymorph<A>, IMonad> DoFor<A>(this Tuple<Polymorph<A>, IMonad> prev, Func<A, Polymorph<A>> f, int times) | |
| { | |
| if (times < 1) throw new ArgumentException(); | |
| var res = prev.Item1; | |
| for (int i = 0; i < times - 1; i++) | |
| { | |
| res = prev.Item2.Bind(res, f); | |
| } | |
| return new Tuple<Polymorph<A>, IMonad>(res, prev.Item2); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment