Help me understand this Scala code: scalaz IO Monad and implicits

admin

Administrator
Staff member
This is a followup to <a href="https://stackoverflow.com/questions/7404495/help-me-understand-this-scala-code-scalaz-io-monad">this</a> question.

Here's the code I'm trying to understand (it's from <a href="http://apocalisp.wordpress.com/2010/10/17/scalaz-tutorial-enumeration-based-io-with-iteratees/" rel="nofollow noreferrer">http://apocalisp.wordpress.com/2010/10/17/scalaz-tutorial-enumeration-based-io-with-iteratees/</a>):

Code:
object io {
  sealed trait IO[A] {
    def unsafePerformIO: A
  }

  object IO {
    def apply[A](a: =&gt; A): IO[A] = new IO[A] {
      def unsafePerformIO = a
    }
  }

  implicit val IOMonad = new Monad[IO] {
    def pure[A](a: =&gt; A): IO[A] = IO(a)
    def bind[A,B](a: IO[A], f: A =&gt; IO[B]): IO[B] = IO {
      implicitly[Monad[Function0]].bind(() =&gt; a.unsafePerformIO,
                                        (x:A) =&gt; () =&gt; f(x).unsafePerformIO)()
    }
  }
}

This code is used like this (I'm assuming an
Code:
import io._
is implied)

Code:
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 =&gt; IO[B], body: A =&gt; IO[C]): IO[C] = for { a &lt;- init
      c &lt;- body(a)
      _ &lt;- 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))

I'm now trying to understand the
Code:
implicit val IOMonad
definition. Here's how I understand it. This is a <a href="http://scalaz.github.com/scalaz/scalaz-2.9.1-6.0.2/doc/index.html#scalaz.Monad" rel="nofollow noreferrer">scalaz.Monad</a>, so it needs to define
Code:
pure
and
Code:
bind
abstract values of the
Code:
scalaz.Monad
trait.

Code:
pure
takes a value and turns it into a value contained in the "container" type. For example it could take an
Code:
Int
and return a
Code:
List[Int]
. This seems pretty simple.

Code:
bind
takes a "container" type and a function that maps the type that the container holds to another type. The value that is returned is the same container type, but it's now holding a new type. An example would be taking a
Code:
List[Int]
and mapping it to a
Code:
List[String]
using a function that maps
Code:
Int
s to
Code:
String
s. Is
Code:
bind
pretty much the same as
Code:
map
?

The implementation of
Code:
bind
is where I'm stuck. Here's the code:

Code:
def bind[A,B](a: IO[A], f: A =&gt; IO[B]): IO[B] = IO {
  implicitly[Monad[Function0]].bind(() =&gt; a.unsafePerformIO,
      (x:A) =&gt; () =&gt; f(x).unsafePerformIO)()
}

This definition takes
Code:
IO[A]
and maps it to
Code:
IO[B]
using a function that takes an
Code:
A
and returns an
Code:
IO[B]
. I guess to do this, it has to use
Code:
flatMap
to "flatten" the result (correct?).

The
Code:
= IO { ... }
is the same as

Code:
 = new IO[A] {
  def unsafePerformIO = implicitly[Monad[Function0]].bind(() =&gt; a.unsafePerformIO,
      (x:A) =&gt; () =&gt; f(x).unsafePerformIO)()
  }
}

I think?

the
Code:
implicitly
method looks for an implicit value (value, right?) that implements
Code:
Monad[Function0]
. Where does this implicit definition come from? I'm guessing this is from the
Code:
implicit val IOMonad = new Monad[IO] {...}
definition, but we're inside that definition right now and things get a little circular and my brain starts to get stuck in an infinite loop :)

Also, the first argument to
Code:
bind
(
Code:
() =&gt; a.unsafePerformIO
) seems to be a function that takes no parameters and returns a.unsafePerformIO. How should I read this?
Code:
bind
takes a container type as its first argument, so maybe
Code:
() =&gt; a.unsafePerformIO
resolves to a container type?