2010-01-02 13 views
23

(Wie) ist es möglich, Monaden in Scala auf eine generische Art und Weise darzustellen (wie die Monad Typenklasse in Haskell)? Ist es irgendwie möglich, einen trait Monad für diesen Zweck zu definieren?Monad-Eigenschaft in Scala

Antwort

40

Man könnte so etwas wie dies versuchen:

trait Monad[+M[_]] { 
    def unit[A](a: A): M[A] 
    def bind[A, B](m: M[A])(f: A => M[B]): M[B] 
} 

// probably only works in Scala 2.8 
implicit def monadicSyntax[M[_], A](m: M[A])(implicit tc: Monad[M]) = new { 
    private val bind = tc.bind(m) _ 

    def map[B](f: A => B) = bind(f compose tc.unit) 

    def flatMap[B](f: A => M[B]) = bind(f) 
} 

implicit object MonadicOption extends Monad[Option] { 
    def unit[A](a: A) = Some(a) 

    def bind[A, B](opt: Option[A])(f: A => Option[B]) = opt flatMap f 
} 

Sie würden natürlich definieren ähnliche implizite Objekte für andere Monade das Herz begehrt. In Haskell-Begriffen können Sie sich wie die Typklasse Monad und MonadicOption als eine bestimmte Instanz dieser Typklasse vorstellen. Die implizite Konvertierung monadicSyntax demonstriert einfach, wie diese Typklasse verwendet werden könnte, um Scalas for -comprehensions mit allem zu ermöglichen, das die Monad typeclass erfüllt.

Im Allgemeinen sind die meisten Dinge in der Scala-Standardbibliothek, die flatMap implementieren, Monaden. Scala definiert keine generische Monad Typklasse (obwohl das sehr nützlich wäre). Stattdessen stützt es sich auf einen syntaktischen Trick des Parsers, um die Verwendung von for -comprehensions mit irgendetwas zu ermöglichen, das die entsprechenden Methoden implementiert. Insbesondere sind diese Methoden map, flatMap und filter (oder foreach und filter für die Imperativform).

+0

Danke, das war genau das, was ich suchte. Ich wollte nur generische Monad-Funktionen und Transformer allgemein definieren ... – Dario

+3

Sie werden das wirklich nicht für etwas wirklich verwenden, oder? :-) Im Ernst, ich arbeite seit einiger Zeit mit Scala, und ich habe festgestellt, dass viele Fälle, in denen Haskell die Monad-Klasse benutzt, in Scala wegen Charakterzügen und Subtyping nicht vorkommen. Die oben angegebene Typenklasse wäre zwar nicht cool, aber sicherlich nicht die idiomatische Lösung von Problemen in Scala. –

+1

Aber sie kommen auf. Sie kommen die ganze Zeit auf. Ein paar Mal am Tag möchte ich 'liftA2' oder' sequenceA'. Zugegeben, diese erfordern nur Applicative statt Monad, aber wenn diese nicht in Ihrer Programmierung auftauchen, dann müssen Sie etwas sehr einfaches schreiben. – Apocalisp

14

Sie können das scalaz Projekt interessant finden; es hat neben einer Implementierung von Monaden noch viele andere (funktionale) Sachen.

2

Scala erreicht eine ähnliche Leistung wie die Haskell-Typklassen durch Verwendung impliziter Parameter, insbesondere von Ansichtsgrenzen und Kontextgrenzen. Sie können solche Dinge besonders auf Scala 2.8 mit Merkmalen wie Ordering und Numeric sehen.

Das heißt, schauen Sie sich das Projekt Scalaz. Es hat Monaden, Funktoren, Pfeile ... den ganzen Shebang.

4

http://www.codecommit.com/blog/ruby/monads-are-not-metaphors

Hier ist ein nützlicher und recht langer Artikel über das Monad Muster und deren Umsetzung in Scala von Daniel verwendet, die die akzeptierten schrieben Antwort für diese Frage.

(Für diejenigen, die über die mystischen Wege der Stackoverflow Website-Suche auf dieser „alte“ Frage stolpern.)