Help me understand this Scala code: scalaz IO Monad
Here's the code I'm trying to understand (it's from http://apocalisp.wordpress.com/2010/10/17/scalaz-tutorial-enumeration-based-io-with-iteratees/):
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) =&g开发者_如何学编程t; () => f(x).unsafePerformIO)()
}
}
}
This code is used like this (I'm assuming an import io._ is implied)
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))
Let's start with the bufferFile definition. Am I correct in thinking that the apply method of io.IO is called? That apply method takes a parameterless function that returns a value (correct?). I guess this is where I'm stuck. Can someone explain how the definition of bufferFile works?
Yes you are right, well almost; io.IO.apply gets called with a so called "by name" parameter which is basically a function which takes nothing (Unit) and returns A. The cool thing about is that when you pass an instance of A directly like new BufferedReader(new FileReader(f)), it will be converted to something like () => new BufferedReader(new FileReader(f)).
As a result of apply you get an instance of an IO[BufferedReader] which defines a method def unsafePerformIO which simply returns the instance of the captured BufferedReader.
Complementing agilesteel's answer, the code
def bufferFile(f: File) = IO { new BufferedReader(new FileReader(f)) }
Is equivalent to
def bufferFile(f: File) = new IO[A] {
def unsafePerformIO = { new BufferedReader(new FileReader(f)) }
}
加载中,请稍侯......
精彩评论