2013-08-11 2 views
5

Könnte mir jemand mit untenstehenden Codebits aus dem Buch helfen?Typ Projektionsbeispiel von "Scala in Action" (Kapitel 8)

trait Mapper[F[_]] { 
    def fmap[A, B](xs: F[A], f: A => B): F[B] 
} 

def VectorMapper = new Mapper[Vector] { 
    def fmap[A, B](xs: Vector[A], f: A => B): Vector[B] = xs map f 
} 

so einfach war: Charakterzug Definition höheren kinded Typen F[_] für die Verwendung mit irgendwelchen „containerartigen“ Typen verwendet, dann einen konkreten Mapper für Vector.

Dann geht ein kniffliger Teil. Mapper für Either. Ich verstehe {type E[A] = Either[X, A]} nur als ein Block des Codes und ({type E[A] = Either[X, A]})#E als eine Projektion, die diesen Typ Alias ​​E aus dem anonymen Block des Codes und von diesem Autor "verbirgt" die Anwesenheit von X für die Eigenschaft, weil Merkmal auf einzelnen Typ funktioniert Parameter "Containertypen" nur - und wir sind interessiert an A, dh Right.

def EitherMapper[X] = new Mapper[({type E[A] = Either[X, A]})#E ] { 
    def fmap[A, B](r: Either[X, A], f: A => B): Either[X, B] = r match { 
     case Left(a) => Left(a) 
     case Right(a) => Right(f(a)) 
    }  
} 

Frage: Warum brauchen wir X im def EitherMapper[X] = Teil?

Danke für Details.

Antwort

4

Entweder ist auf zwei Arten abhängig, zum Beispiel Either[Int, String]

EitherMapper ein Typkonstruktor ist, die nur auf einen Typ abhängig ist, so, wenn Sie eine EitherMapper[Int] haben, Sie sind mit einem Either[Int, A] tun haben, und A wird aufgelöst in der Mapper-Teil, so können Sie jede A=>B Funktion haben, da der erste Typ von Either bereits für den Mapper vorhanden ist und Sie eine Either[X, B] zurückgeben.

Tatsächlich ist der Typ E [A] äquivalent zu Entweder [X, A], Sie haben nur einen Freiheitsgrad in Bezug auf Typen!

val right: Either[Boolean, String] = Right("test") 
val left: Either[Boolean, String] = Left(false) 

println(EitherMapper.fmap(right, (s: String) => s.length)) 
> Right(4) 
println(EitherMapper.fmap(left, (s: String) => s.length)) 
> Left(false) 

In diesem Fall ist der Typ EitherMapper[Boolean] ist und die Art der fmap ist fmap[String, Integer], nimmt es Either[Boolean, String] und zurück Either[Boolean, Integer].

Wie Sie die Art der fmap sagt nichts über den am Ende X Teil der so Either[X, A] Art sehen Sie die (s: String) => s.length) Funktion für andere EitherMapper[X] Arten, in einfachen Worten den „linken“ Teil des Einsatz könnten jeder Typ kann alles sein, was Sie wollen, und es ist der "X" -Teil der Typkonstruktion.

Hoffe, es ist jetzt klarer!

+1

Vincenzo, hi. Könnten Sie bitte die Verwendung des "Entweder-Mappers" illustrieren, könnte dies klarer werden? Ich frage das, weil, sagen wir, für 'VectorMapper' ist es einfach wie 'val v = VectorMapper.fmap (einigeVectorOfInts, _ => _ * 2)' – Max

+0

Ja, warte nur ein wenig, weil ich meine nehmen muss Laptop, wo ich Scala –

+0

installiert habe Beispiel hinzugefügt !!! –