Es gibt einige Verwendungen:
PartialFunction
Denken Sie daran, dass a PartialFunction[A, B]
eine Funktion ist, die für eine Teilmenge der Domäne definiert ist A
(wie von der isDefinedAt
Methode angegeben). Sie können ein PartialFunction[A, B]
in ein "heben" Function[A, Option[B]]
. Das heißt, eine Funktion über die definierte ganze von A
aber , deren Werte vom TypOption[B]
Dies erfolgt durch den expliziten Aufruf der Methode lift
am PartialFunction
.
scala> val pf: PartialFunction[Int, Boolean] = { case i if i > 0 => i % 2 == 0}
pf: PartialFunction[Int,Boolean] = <function1>
scala> pf.lift
res1: Int => Option[Boolean] = <function1>
scala> res1(-1)
res2: Option[Boolean] = None
scala> res1(1)
res3: Option[Boolean] = Some(false)
Methoden
Sie können einen Methodenaufruf in eine Funktion "heben". Dies nennt man eta-Expansion (danke an Ben James dafür). Also zum Beispiel:
scala> def times2(i: Int) = i * 2
times2: (i: Int)Int
Wir heben eine Methode in eine Funktion auf, indem wir den Unterstrich anwenden
scala> val f = times2 _
f: Int => Int = <function1>
scala> f(4)
res0: Int = 8
Beachten Sie den grundlegenden Unterschied zwischen Methoden und Funktionen. res0
ist eine Instanz (dh ein Wert ) vom Typ (Funktions-)(Int => Int)
Funktoren
Ein Funktor (wie von scalaz definiert ) ist ein "Container" (ich verwende den Begriff extrem locker), F
so dass wir, wenn wir eine F[A]
und eine Funktion haben A => B
, einen in die Hände bekommen können F[B]
(denken Sie zum Beispiel an F = List
die map
Methode) )
Wir können diese Eigenschaft wie folgt codieren:
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
Dies ist isomorph, um die Funktion A => B
in die Domäne des Funktors "heben" zu können . Das ist:
def lift[F[_]: Functor, A, B](f: A => B): F[A] => F[B]
Das heißt, wenn F
es sich um einen Funktor handelt und wir eine Funktion haben A => B
, haben wir eine Funktion F[A] => F[B]
. Sie könnten versuchen, die lift
Methode zu implementieren - sie ist ziemlich trivial.
Monadentransformatoren
Wie hcoopz weiter unten sagt (und ich habe gerade festgestellt, dass ich dadurch nicht eine Menge unnötigen Codes geschrieben hätte), hat der Begriff "Lift" auch innerhalb von Monad Transformers eine Bedeutung . Denken Sie daran, dass Monadentransformatoren eine Möglichkeit sind, Monaden übereinander zu "stapeln" (Monaden komponieren nicht).
Angenommen, Sie haben eine Funktion, die eine zurückgibt IO[Stream[A]]
. Dies kann in den Monadentransformator umgewandelt werden StreamT[IO, A]
. Jetzt möchten Sie vielleicht einen anderen Wert "anheben" und IO[B]
vielleicht ist es auch ein StreamT
. Sie könnten entweder Folgendes schreiben:
StreamT.fromStream(iob map (b => Stream(b)))
Oder dieses:
iob.liftM[StreamT]
das wirft die frage auf: warum möchte ich ein IO[B]
in ein umwandeln StreamT[IO, B]
? . Die Antwort wäre "Kompositionsmöglichkeiten nutzen". Angenommen, Sie haben eine Funktionf: (A, B) => C
lazy val f: (A, B) => C = ???
val cs =
for {
a <- as
b <- bs.liftM[StreamT]
}
yield f(a, b)
cs.toStream