帮助我理解这个Scala代码:scalaz IO Monad

thr*_*ups 4 monads scala

这是我试图理解的代码(来自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) => () => f(x).unsafePerformIO)()
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这段代码是这样使用的(我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))
Run Code Online (Sandbox Code Playgroud)

让我们从bufferFile定义开始.我是否认为applyio.IO 的方法被调用了?该apply方法采用无参数函数返回一个值(正确?).我想这就是我被困住的地方.有人可以解释一下如何定义bufferFile作品吗?

agi*_*eel 5

是的,你是对的,差不多; io.IO.apply使用所谓的"by name"参数调用,该参数基本上是一个不带(Unit)并返回的函数A.很酷的是,当你A直接传递一个实例时new BufferedReader(new FileReader(f)),它会被转换成类似的东西() => new BufferedReader(new FileReader(f)).

因此,apply您将获得一个IO[BufferedReader]定义一个方法def unsafePerformIO的实例,该方法只返回捕获的实例BufferedReader.