2010-04-05 12 views
7

Ich versuche höhere Ordnung polymophism in scala zu erreichen durch eine sehr einfache Schnittstelle implementiert, die eine Monade beschreibt aber stoße ich auf ein Problem, das ich nicht wirklich verstehen.Gängige Praxis für höhere Ordnung Polymorphismus in scala

implementiert ich das gleiche mit C++ und der Code sieht wie folgt aus:

#include <iostream> 

template <typename T> 
class Value { 
private: 
    T value; 
public: 
    Value(const T& t) { 
    this->value = t; 
    } 

    T get() { 
    return this->value; 
    } 
}; 

template < template <typename> class Container > 
class Monad { 
public: 
    template <typename A> Container<A> pure(const A& a); 
}; 

template <template <typename> class Container> 
    template <typename A> 
Container<A> Monad<Container>::pure(const A& a) { 
    return Container<A>(a); 
} 

int main() { 
    Monad<Value> m; 
    std::cout << m.pure(1).get() << std::endl; 
    return 0; 
} 

Wenn mit scala das Gleiche zu tun versuchen, scheitern I:

class Value[T](val value: T) 

class Monad[Container[T]] { 
    def pure[A](a: A): Container[A] = 
    Container[A](a) 
} 

object Main { 
    def main(args: Array[String]): Unit = { 
    val m = new Monad[Value] 
    m.pure(1) 
    } 
} 

Der Compiler beschwert sich über:

[[email protected]:Scala]:434> scalac highorder.scala 
highorder.scala:5: error: not found: value Container 
    Container[A](a) 
    ^
one error found 

Was mache ich hier falsch? Es scheint ein grundlegendes Konzept zu sein, ich scheine nicht über scala typeconstructors zu verstehen.

Grüße, raichoo

+0

http://stackoverflow.com/questions/1992532/monad-trait-in-scala – missingfaktor

+0

Danke, dieser Link sieht sehr interessant aus, aber beantwortet meine Frage nicht wirklich. Ich wollte nichts über Monaden wissen, meine Frage war über Typkonstruktorpolymorphismus. Trotzdem sieht es nach einer guten Lektüre aus. :) – raichoo

Antwort

16

Der Monad Zug in Scala wären wie folgt erklärt:

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

Beachten sie, dass es mit einem Typkonstruktor M[_] parametriert wird. Der Klammerunterstrich zeigt an, dass M ein Typenkonstruktor von Art(* -> *) ist (d. H. M benötigt einen Typ A, um einen Typ M[A] zu konstruieren). Ihre Identität Monade Instanz würde dann wie folgt geschrieben werden:

class Value[A](a: => A) { lazy val value = a } 

implicit val identityMonad = new Monad[Value] { 
    def pure[A](a: => A) = new Value(a) 
    def bind[A,B](a: Value[A], f: A => Value[B]) = new Value(f(a.value).value) 
} 

Diese Definition verwendet by-name Parameter faul Semantik zu erreichen.

Monad und andere nützliche höher Klassen Klassen werden von der Scalaz Bibliothek zusammen mit einer Vielzahl von Instanzen für die Standard-Java/Scala-Bibliotheken zur Verfügung gestellt.

+0

Erstaunlich, mein Kopf explodierte einfach, aber das war das was ich gesucht habe. Vielen Dank :) – raichoo

3

nicht sicher, was die beste Lösung wäre, aber in der Definition von reinen im Code:

class Monad[Container[T]] { 
    def pure[A](a: A): Container[A] = Container[A](a) 
} 

Welche Container[A](a) tun soll? Bisher haben Sie Container als generischen Typen XXX definiert und Sie haben keine Informationen darüber, wie ein neues Objekt zu bauen. Sie müssen ein Builder-Objekt als impliziten Parameter übergeben. Werfen Sie einen Blick darauf, wie die Sammlung Bibliotheken in Scala umgesetzt werden 2,8 oder die Monade Definition in Scalaz

5

Wenn Sie Ihre Definition der Monad Klasse die Container[_]

class Monad[Container[_]] {   
    def pure[A <% Container[A]](a: A): Container[A] = a 
} 

Die Syntax folgt ändern sind, wie höhere Arten sind in Scala ausgedrückt. Die A <% Container[A] ist eine ‚Ansicht gebunden‘, das zum Ausdruck bringt, dass A zu Container[A] implizit konvertierbar ist. Der Textkörper der Methode verwendet diese implizite Konvertierung. Um diese Klasse zu verwenden, müssen Sie für eine implizite Konvertierung in ihrem Umfang haben (in Ihrem Beispiel) Int zu Value[Int]

implicit def toValue[T](t:T) = new Value(t) 

Sie können dann folgendermaßen

scala> val m = new Monad[Value]      
m: Monad[Value] = [email protected] 

scala> m.pure(1).value   
res3: Int = 1 
+0

Sorry Container [_] ist in Scala kein höherer Typ, wie ich gerade in [Was ist ein höherstufiger Typ-in-Scala] gelernt hat (http://stackoverflow.com/questions/6246719)/Was-ist-ein-höher-kinded-type-in-scala) – Lutz

Verwandte Themen