2010-04-05 13 views
7

Próbuję uchwycić wyższość-polymofizm w scala poprzez wdrożenie bardzo prostego interfejsu opisującego monadę, ale napotykam problem, którego tak naprawdę nie rozumiem.Powszechna praktyka polimorfizmu wyższego rzędu w scala

I wdrożone samo z C++ i kod wygląda następująco:

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

Gdy próbuje zrobić to samo z Scala zawiodę:

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

Kompilator narzeka na temat:

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

Co ja tu robię źle? Wydaje się, że istnieje podstawowa koncepcja, której nie rozumiem w odniesieniu do typowych konstruktorów scala.

Pozdrawiam, raichoo

+0

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

+0

Dzięki, ten link wygląda bardzo interesująco, ale tak naprawdę nie odpowiada na moje pytanie. Nie chciałem nic wiedzieć o monadach, moje pytanie dotyczyło polimorfizmu konstruktora typu. Mimo to wygląda na dobry odczyt. :) – raichoo

Odpowiedz

16

Monad cecha w Scala byłoby zadeklarowana następująco:

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

Zauważ, że to parametryzowane z konstruktora typu M[_]. Podkreślony podkreślnik wskazuje, że M jest konstruktorem typu rodzaju(* -> *) (tj. M bierze pewien typ A w celu skonstruowania typu M[A]). Twoja instancja monady tożsamości zostanie napisana w następujący sposób:

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

Ta definicja wykorzystuje parametry nazwy użytkownika do osiągnięcia leniwych semantyki.

Monady i inne przydatne klasy o wyższych klasach są dostarczane przez bibliotekę Scalaz wraz z wieloma instancjami dla standardowych bibliotek Java/Scala.

+0

Niesamowite, moja głowa eksplodowała, ale tego właśnie szukałem. Dzięki :) – raichoo

3

Nie wiem, co byłoby najlepszym rozwiązaniem, ale w definicji czystego kodu:

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

Co Container[A](a) powinien zrobić? Do tej pory zdefiniowałeś kontener jako rodzajowy typ XXX i nie masz żadnych informacji o tym, jak zbudować nowy obiekt. Musisz przekazać obiekt "budowniczy" jako niejawny parametr. Spójrz jak biblioteki kolekcji są realizowane w Scala 2.8 lub definicji Monad w Scalaz

5

Jeśli zmienisz definicję klasy Monad z następującym

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

The składni Container[_] sposób wyższe rodzaje są wyrażone w Scali. A <% Container[A] to "powiązanie widoku", które oznacza, że ​​A jest domyślnie wymienialne na Container[A]. Treść metody korzysta z tej niejawnej konwersji. Aby skorzystać z tej klasy, trzeba mieć niejawna konwersja w zakres (w Twojej przykład) Int do Value[Int]

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

Następnie można wykonać następujące czynności

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

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

Niestety Container [_] nie jest typem wyższego rodzaju w Scali, jak właśnie nauczyłem się w [co-jest-a-wyższym-rodzaju-w-scala] (http://stackoverflow.com/questions/6246719/co-jest-a-wyższym-rodzaju-w-scala) – Lutz

Powiązane problemy