Помогите мне понять этот код Scala: скалаз IO Monad и последствия

Это продолжение кэто вопрос.

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

Я сейчас пытаюсь понятьimplicit val IOMonad определение. Вот как я это понимаю. Этоscalaz.Monadтак что нужно определитьpure а такжеbind абстрактные значенияscalaz.Monad черта характера.

pure принимает значение и превращает его в значение, содержащееся в типе «контейнер». Например, это может занятьInt и вернутьList[Int], Это кажется довольно простым.

bind принимает тип «контейнер» и функцию, которая отображает тип, который контейнер содержит, на другой тип. Возвращаемое значение имеет тот же тип контейнера, но теперь оно содержит новый тип. Примером будет взятьList[Int] и сопоставление его сList[String] используя функцию, которая отображаетIntсStrings. Является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 разрешается к типу контейнера?

Ответы на вопрос(1)

Ваш ответ на вопрос