Ada beberapa penggunaan:
Fungsi Sebagian
Ingat a PartialFunction[A, B]
adalah fungsi yang didefinisikan untuk beberapa subset domain A
(sebagaimana ditentukan oleh isDefinedAt
metode). Anda bisa "mengangkat" PartialFunction[A, B]
a Function[A, Option[B]]
. Artinya, fungsi yang didefinisikan atas seluruh dari A
namun yang nilai adalah dari jenisOption[B]
Ini dilakukan oleh doa eksplisit metode lift
pada 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)
Metode
Anda dapat "mengangkat" pemanggilan metode ke suatu fungsi. Ini disebut ekspansi eta (terima kasih kepada Ben James untuk ini). Jadi misalnya:
scala> def times2(i: Int) = i * 2
times2: (i: Int)Int
Kami mengangkat metode ke fungsi dengan menerapkan garis bawah
scala> val f = times2 _
f: Int => Int = <function1>
scala> f(4)
res0: Int = 8
Perhatikan perbedaan mendasar antara metode dan fungsi. res0
adalah turunan (yaitu nilai ) dari tipe (fungsi)(Int => Int)
Functors
Sebuah functor (seperti yang didefinisikan oleh scalaz ) adalah beberapa "wadah" (Saya menggunakan istilah ini dengan sangat longgar), F
sehingga, jika kita memiliki F[A]
dan fungsi A => B
, maka kita bisa mendapatkan tangan kita F[B]
(pikirkan, misalnya, F = List
dan map
metode )
Kami dapat menyandikan properti ini sebagai berikut:
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
Ini isomorfik untuk dapat "mengangkat" fungsi A => B
ke domain functor. Itu adalah:
def lift[F[_]: Functor, A, B](f: A => B): F[A] => F[B]
Artinya, jika F
adalah functor, dan kami memiliki fungsi A => B
, kami memiliki fungsi F[A] => F[B]
. Anda mungkin mencoba dan menerapkan lift
metode ini - ini cukup sepele.
Transformers Monad
Seperti yang dikatakan hcoopz di bawah ini (dan saya baru menyadari bahwa ini akan menyelamatkan saya dari menulis satu ton kode yang tidak perlu), istilah "lift" juga memiliki arti di dalam Monad Transformers . Ingatlah bahwa transformer monad adalah cara "menumpuk" monad di atas satu sama lain (monad tidak menulis).
Jadi misalnya, misalkan Anda memiliki fungsi yang mengembalikan sebuah IO[Stream[A]]
. Ini dapat dikonversi ke trafo monad StreamT[IO, A]
. Sekarang Anda mungkin ingin "mengangkat" beberapa nilai lain dan IO[B]
mungkin juga merupakan StreamT
. Anda bisa menulis ini:
StreamT.fromStream(iob map (b => Stream(b)))
Atau ini:
iob.liftM[StreamT]
ini menimbulkan pertanyaan: mengapa saya ingin mengubah sebuah IO[B]
menjadi StreamT[IO, B]
? . Jawabannya adalah "untuk mengambil keuntungan dari kemungkinan komposisi". Katakanlah Anda memiliki fungsif: (A, B) => C
lazy val f: (A, B) => C = ???
val cs =
for {
a <- as //as is a StreamT[IO, A]
b <- bs.liftM[StreamT] //bs was just an IO[B]
}
yield f(a, b)
cs.toStream //is a Stream[IO[C]], cs was a StreamT[IO, C]