Помогите мне понять этот код Scala: скалаз IO Monad - PullRequest
4 голосов
/ 13 сентября 2011

Вот код, который я пытаюсь понять (это от 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)()
    }
  }
}

Этот код используется следующим образом (я предполагаю, что 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))

Давайте начнем с определения bufferFile. Правильно ли я считаю, что метод io.IO apply вызывается? Этот метод apply принимает функцию без параметров, которая возвращает значение (правильно?). Я думаю, это то, где я застрял. Может кто-нибудь объяснить, как работает определение bufferFile?

Ответы [ 2 ]

5 голосов
/ 13 сентября 2011

Да, вы правы, ну почти; io.IO.apply вызывается с так называемым параметром «по имени», который в основном является функцией, которая ничего не берет (Unit) и возвращает A. Крутая вещь в том, что когда вы передаете экземпляр A непосредственно как new BufferedReader(new FileReader(f)), он будет преобразован во что-то вроде () => new BufferedReader(new FileReader(f)).

В результате apply вы получаете экземпляр IO[BufferedReader], который определяет метод def unsafePerformIO, который просто возвращает экземпляр захваченного BufferedReader.

2 голосов
/ 14 сентября 2011

Дополняет Agilesteel * ответ , код

def bufferFile(f: File) = IO {   new BufferedReader(new FileReader(f)) }

Эквивалентно

def bufferFile(f: File) = new IO[A] {
  def unsafePerformIO = { new BufferedReader(new FileReader(f)) }
}
...