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]
MonadTrans
instanceT
untukM
danMonad
instance untukN
, makaT.liftM
dapat digunakan untuk mengangkat nilai tipeN[A]
ke nilai tipeM[N, A]
.liftM
untuk itu, tetapi tidak berhasil mengerti bagaimana melakukannya dengan benar. Kawan, kau batu!f
seharusnya sebuah instance, bukanres0
?Penggunaan lain dari pengangkatan yang pernah saya temui di kertas (tidak harus terkait dengan Scala) adalah kelebihan fungsi dari
f: A -> B
denganf: List[A] -> List[B]
(atau set, multiset, ...). Ini sering digunakan untuk menyederhanakan formalisasi karena tidak masalah apakahf
diterapkan pada elemen individu atau beberapa elemen.Overloading semacam ini sering dilakukan secara deklaratif, misalnya,
atau
atau secara imperatif, misalnya,
sumber
Perhatikan setiap koleksi yang memanjang
PartialFunction[Int, A]
(seperti yang ditunjukkan oleh oxbow_lakes) dapat diangkat; jadi misalnyayang mengubah fungsi parsial menjadi fungsi total di mana nilai-nilai yang tidak didefinisikan dalam koleksi dipetakan
None
,Bahkan,
Ini menunjukkan pendekatan yang rapi untuk menghindari pengecualian indeks .
sumber
Ada juga unlifting , yang merupakan proses terbalik untuk mengangkat.
Jika mengangkat didefinisikan sebagai
maka unlifting adalah
Perpustakaan standar Scala didefinisikan
Function.unlift
sebagaiSebagai contoh, play-json library menyediakan unlift untuk membantu pembangunan serialis JSON :
sumber