यह this प्रश्न का अनुवर्ती है।मुझे इस स्कैला कोड को समझने में सहायता करें: स्कालाज़ आईओ मोनाड और implicits
object io {
sealed trait IO[A] {
def unsafePerformIO: A
}
object IO {
def apply[A](a: => A): IO[A] = new IO[A] {
def unsafePerformIO = a
}
}
implicit val IOMonad = new Monad[IO] {
def pure[A](a: => A): IO[A] = IO(a)
def bind[A,B](a: IO[A], f: A => IO[B]): IO[B] = IO {
implicitly[Monad[Function0]].bind(() => a.unsafePerformIO,
(x:A) =>() => f(x).unsafePerformIO)()
}
}
}
यह (मैं एक import io._
निहित है संभालने हूँ) कोड इस तरह प्रयोग किया जाता है
def bufferFile(f: File) = IO { new BufferedReader(new FileReader(f)) }
def closeReader(r: Reader) = IO { r.close }
def bracket[A,B,C](init: IO[A], fin: A => IO[B], body: A => IO[C]): IO[C] = for { a <- init
c <- body(a)
_ <- fin(a) } yield c
def enumFile[A](f: File, i: IterV[String, A]): IO[IterV[String, A]] = bracket(bufferFile(f),
closeReader(_:BufferedReader),
enumReader(_:BufferedReader, i))
मैं:
यहाँ कोड मैं (यह http://apocalisp.wordpress.com/2010/10/17/scalaz-tutorial-enumeration-based-io-with-iteratees/ से है) को समझने के लिए कोशिश कर रहा हूँ है अब मैं implicit val IOMonad
परिभाषा को समझने की कोशिश कर रहा हूं। यहां बताया गया है कि मैं इसे कैसे समझता हूं। यह scalaz.Monad है, इसलिए scalaz.Monad
विशेषता के pure
और bind
अमूर्त मूल्यों को परिभाषित करने की आवश्यकता है।
pure
एक मूल्य लेता है और इसे "कंटेनर" प्रकार में निहित मान में बदल देता है। उदाहरण के लिए यह Int
ले सकता है और List[Int]
लौटा सकता है। यह बहुत आसान लगता है।
bind
एक "कंटेनर" प्रकार और एक फ़ंक्शन लेता है जो कंटेनर किसी अन्य प्रकार के प्रकार को मानचित्र करता है। लौटाया जाने वाला मान एक ही कंटेनर प्रकार है, लेकिन अब यह एक नया प्रकार है। एक उदाहरण List[Int]
ले जाएगा और List[String]
पर उस फ़ंक्शन का उपयोग करके मैपिंग करेगा जो Int
s से String
s पर नक्शा रखता है। bind
map
के समान ही है?
bind
का कार्यान्वयन जहां मैं अटक गया हूं। कोड यह रहा:
def bind[A,B](a: IO[A], f: A => IO[B]): IO[B] = IO {
implicitly[Monad[Function0]].bind(() => a.unsafePerformIO,
(x:A) =>() => f(x).unsafePerformIO)()
}
इस परिभाषा IO[A]
लेता है और IO[B]
के लिए यह एक ऐसा कार्य है जो एक A
लेता है और एक IO[B]
रिटर्न का उपयोग कर। मुझे ऐसा करने का अनुमान है, इसे flatMap
का उपयोग परिणाम को "फ़्लैट" करने के लिए करना है (सही?)।
= IO { ... }
= new IO[A] {
def unsafePerformIO = implicitly[Monad[Function0]].bind(() => a.unsafePerformIO,
(x:A) =>() => f(x).unsafePerformIO)()
}
}
मुझे लगता है कि के रूप में ही है?
implicitly
विधि एक अंतर्निहित मूल्य (मान, दाएं?) की तलाश करता है जो Monad[Function0]
लागू करता है। यह अंतर्निहित परिभाषा कहां से आती है? मुझे लगता है कि यह implicit val IOMonad = new Monad[IO] {...}
परिभाषा से है, लेकिन हम अभी उस परिभाषा के अंदर हैं और चीजें थोड़ा गोलाकार हो जाती हैं और मेरा दिमाग एक अनंत लूप में फंस जाता है :)
इसके अलावा, bind
पर पहला तर्क (() => a.unsafePerformIO
) ऐसा प्रतीत होता है जो कोई पैरामीटर नहीं लेता है और a.unsafePerformIO देता है। मुझे इसे कैसे पढ़ा जाना चाहिए? bind
एक कंटेनर प्रकार को अपना पहला तर्क के रूप में लेता है, तो शायद () => a.unsafePerformIO
एक कंटेनर प्रकार के लिए हल हो सकता है?
Scalaz वास्तव में एक आईओ इकाई बॉक्स से बाहर अब प्रदान करता है। आयात scalaz.effects._ – Apocalisp