कुछ उपयोग हैं:
PartialFunction
याद रखें एक PartialFunction[A, B]
फ़ंक्शन डोमेन के कुछ सबसेट के लिए परिभाषित किया गया है A
(जैसा कि isDefinedAt
विधि द्वारा निर्दिष्ट है )। आप एक PartialFunction[A, B]
में "लिफ्ट" कर सकते हैं Function[A, Option[B]]
। वह है, एक ऐसा फंक्शन जिसे पूरे में परिभाषित किया गया है A
लेकिन जिसका मान प्रकार का हैOption[B]
इस विधि का स्पष्ट मंगलाचरण द्वारा किया जाता है lift
पर 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)
तरीके
आप एक फ़ंक्शन में एक विधि मंगलाचरण "उठा" सकते हैं। इसे एटा-विस्तार कहा जाता है (इसके लिए बेन जेम्स का धन्यवाद)। उदाहरण के लिए:
scala> def times2(i: Int) = i * 2
times2: (i: Int)Int
हम अंडरस्कोर को लागू करके फ़ंक्शन में एक विधि उठाते हैं
scala> val f = times2 _
f: Int => Int = <function1>
scala> f(4)
res0: Int = 8
विधियों और कार्यों के बीच मूलभूत अंतर पर ध्यान दें। res0
एक उदाहरण है (यानी यह एक मान है ) (फ़ंक्शन) प्रकार का(Int => Int)
functors
एक functor (के रूप में द्वारा परिभाषित scalaz ) कुछ "कंटेनर" (मैं शब्द का प्रयोग है अत्यंत शिथिल), F
ऐसा है कि, अगर हम एक है F[A]
और एक समारोह A => B
है, तो हम अपने हाथों एक पर प्राप्त कर सकते हैं F[B]
(लगता है, उदाहरण के लिए, F = List
और map
विधि )
हम इस संपत्ति को निम्नानुसार सांकेतिक शब्दों में बदलना कर सकते हैं:
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
यह इसोमॉर्फिक है जो फंक्शनल A => B
के डोमेन में फ़ंक्शन को "लिफ्ट" करने में सक्षम है । अर्थात्:
def lift[F[_]: Functor, A, B](f: A => B): F[A] => F[B]
यही है, अगर F
एक फ़नकार है, और हमारे पास एक फ़ंक्शन है A => B
, तो हमारे पास एक फ़ंक्शन है F[A] => F[B]
। आप कोशिश कर सकते हैं और lift
विधि को लागू कर सकते हैं - यह बहुत तुच्छ है।
मोनाड ट्रांसफॉर्मर
जैसा कि hcoopz नीचे कहता है (और मुझे अभी पता चला है कि इससे मुझे एक टन अनावश्यक कोड लिखने से बचाया गया होगा), "लिफ्ट" शब्द का भी मोनाड ट्रांसफॉर्मर्स के भीतर एक अर्थ है । स्मरण करो कि एक भिक्षु ट्रांसफार्मर एक दूसरे के शीर्ष पर "स्टैकिंग" मठों का एक तरीका है (मठ रचना नहीं करते हैं)।
इसलिए, उदाहरण के लिए, मान लीजिए कि आपके पास एक फ़ंक्शन है जो एक रिटर्न देता है IO[Stream[A]]
। इसे मोनड ट्रांसफार्मर में परिवर्तित किया जा सकता है StreamT[IO, A]
। अब आप शायद कुछ और "मूल्य" उठाना IO[B]
चाहते हैं कि यह भी एक है StreamT
। आप इसे लिख सकते हैं:
StreamT.fromStream(iob map (b => Stream(b)))
या यह:
iob.liftM[StreamT]
यह सवाल है: क्यों मैं एक IO[B]
में एक में परिवर्तित करना चाहते हैं StreamT[IO, B]
? । इसका उत्तर "संरचना संभावनाओं का लाभ उठाना" होगा। मान लीजिए कि आपके पास एक फ़ंक्शन हैf: (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]