2010-04-05 18 views
7

sto cercando di cogliere di ordine superiore-polymophism in scala mediante l'attuazione di un'interfaccia molto semplice che descrive una monade, ma ho incontrato un problema che non capisco.pratica comune per ordine superiore-polimorfismo in scala

ho implementato lo stesso con C++ e il codice simile a questo:

#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; 
} 

Nel provare a fare lo stesso con scala fallisco:

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) 
    } 
} 

Il compilatore si lamenta:

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

Cosa sto facendo di sbagliato qui? Sembra che ci sia un concetto fondamentale che non mi sembra di capire su scala typeconstructors.

saluti, raichoo

+0

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

+0

Grazie, il collegamento sembra molto interessante ma in realtà non risponde alla mia domanda. Non volevo sapere nulla delle monadi, la mia domanda riguardava il polimorfismo del costruttore del tipo. Anche se sembra una buona lettura. :) – raichoo

risposta

16

Il Monad tratto a Scala sarebbe dichiarato come segue:

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

Nota che è parametrizzato con un tipo di costruttore di M[_]. La sottolineatura tra parentesi indica che M è un costruttore di tipo tipo(* -> *) (ad esempio M utilizza un tipo A per creare un tipo M[A]). Il vostro esempio identità monade sarebbe quindi essere scritta in questo modo:

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) 
} 

Questa definizione utilizza parametri per nome per ottenere la semantica pigri.

Monade e le altre classi di tipo alto-kinded utili sono forniti dalla libreria Scalaz insieme a un sacco di istanze per le librerie standard di Java/Scala.

+0

Incredibile, la mia testa è esplosa, ma era quello che stavo cercando. Grazie :) – raichoo

3

Non sei sicuro di quello che sarebbe la soluzione migliore, ma nella definizione di puro nel codice:

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

Cosa Container[A](a) dovrebbe fare? Finora, hai definito Contenitore come tipo generico XXX e non hai informazioni su come creare un nuovo oggetto. È necessario passare un oggetto "builder" come parametro implicito. Date un'occhiata a come le librerie di raccolta sono implementati in Scala 2.8 o la definizione Monade in Scalaz

5

Se si cambia la definizione della classe Monad al seguente

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

La sintassi Container[_] è come i tipi più elevati sono espressi in Scala. Lo A <% Container[A] è un "limite di visualizzazione" che esprime che A è implicitamente convertibile in Container[A]. Il corpo del metodo utilizza questa conversione implicita. Per utilizzare questa classe, è necessario disporre di una conversione implicita nella possibilità di (nel tuo esempio) Int a Value[Int]

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

Si può quindi effettuare le seguenti

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

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

Il contenitore dei commenti [_] non è un tipo con caratteri più elevati in Scala come ho appena imparato in [cosa-è-un-tipo-superiore-in-scala più alto] (http://stackoverflow.com/questions/6246719/che-è-un-superiore-tipo-in-scala) – Lutz

Problemi correlati