Έχουν δημοσιευτεί Κυριακή, 25 Οκτωβρίου 2009 5:34 μμ από το μέλος PALLADIN

Abstracting over 'M'

Τον τελευταίο καιρό ψάχνω κάποιο φορμαλισμό (σε C#) ώστε να μπορέσω να έχω έναν generic-reusable ορισμό ενός Monad.
Αυτό που λείπει από τα .Net generics είναι η δυνατότητα να έχω abstraction σε επίπεδο Type Constructor.

Σαν παράδειγμα της συγκεκριμένης αφαίρεσης, παρουσιάζω τον generic ορισμό ενός Monad μέσα από δυο αγαπημένες μου γλώσσες.

Haskell
class Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  return :: a -> m a


Scala
class Monad[M[_]] {
	def unit[T](a: T): M[T]
	def bind[T, K](m: M[T], f: T => M[K]): M[K]
}
Μετά από αρκετό πειραματισμό και μελέτη, κατέληξα στον παρακάτω κώδικα.
	abstract class Monad<T, M> where M : MonadDef<M> { }
	abstract class MonadDef<M> where M : MonadDef<M>
	{
		public abstract Monad<T, M> Unit<T>(T value);
		public abstract Monad<S, M> Bind<T, S>(Monad<T, M> monad, Func<T, Monad<S, M>> func);

		public Monad<S, M> Then<T, S>(Monad<T, M> first, Monad<S, M> second)
		{
			return Bind(first, _ => second);
		}

		public Monad<S, M> Map<T, S>(Monad<T, M> monad, Func<T, S> f)
		{
			return Bind(monad, value => Unit(f(value)));
		}

		public Monad<T, M> Join<T>(Monad<Monad<T, M>, M> monad)
		{
			return Bind(monad, value => value);
		}
	}
	// Maybe Monad implementation 
	abstract class Maybe<T> : Monad<T, MaybeDef>
	{
	}
	sealed class Just<T> : Maybe<T>
	{
		public T Value { private set; get; }
		public Just(T value) { Value = value; }
	}
	sealed class Nothing<T> : Maybe<T> { }

	static class MaybeMonadExtensions
	{
		public static Maybe<T> ToMaybe<T>(this Monad<T, MaybeDef> monad)
		{
			return (Maybe<T>)monad;
		}
	}

	sealed class MaybeDef : MonadDef<MaybeDef>
	{

		public override Monad<T, MaybeDef> Unit<T>(T value)
		{
			return new Just<T>(value);
		}

		public override Monad<S, MaybeDef> Bind<T, S>(Monad<T, MaybeDef> monad, Func<T, Monad<S, MaybeDef>> f)
		{
			Just<T> just = monad as Just<T>;
			if (just != null)
				return f(just.Value);
			else
				return new Nothing<S>();
		}
	}
 
         static void Main(string[] args)
	{
            var def = new MaybeDef();
            Maybe<string> result = def.Bind(def.Unit(42), value => def.Unit(value.ToString())).ToMaybe();
         }
Share


Ενημέρωση για Σχόλια

Αν θα θέλατε να λαμβάνετε ένα e-mail όταν γίνονται ανανεώσεις στο περιεχόμενο αυτής της δημοσίευσης, παρακαλούμε γίνετε συνδρομητής εδώ

Παραμείνετε ενήμεροι στα τελευταία σχόλια με την χρήση του αγαπημένου σας RSS Aggregator και συνδρομή στη Τροφοδοσία RSS με σχόλια

Σχόλια:

 

napoleon έγραψε:

Να ρωτήσω(...) γιατί δεν το επιχείρησες σε F# μιας και θα ήταν χρησιμοποιήσιμο από .ΝΕΤ και πιο εύκολο;

Οκτωβρίου 25, 2009 8:11 μμ
 

PALLADIN έγραψε:

Kai o F# codikas den einai diaforetikos, epeidi einai limitation ton .net generics.

Οκτωβρίου 25, 2009 9:30 μμ
 

Thoughts and Code έγραψε:

Μετά από αρκετές αποτυχημένες προσπάθειες, στο να συνδυάσω Type constructor polymorphism και LINQ syntax,

Δεκεμβρίου 20, 2009 3:55 μμ

Ποιά είναι η άποψή σας για την παραπάνω δημοσίευση;

(απαιτούμενο)
απαιτούμενο
προαιρετικό
απαιτούμενο
ÅéóÜãåôå ôïí êùäéêü:
CAPTCHA Image