Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6580835
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 25, 20262026-05-25T16:04:36+00:00 2026-05-25T16:04:36+00:00

This is a followup to this question. Here’s the code I’m trying to understand

  • 0

This is a followup to this question.

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) => () => 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))

I’m now trying to understand the implicit val IOMonad definition. Here’s how I understand it. This is a scalaz.Monad, so it needs to define pure and bind abstract values of the scalaz.Monad trait.

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

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 List[Int] and mapping it to a List[String] using a function that maps Ints to Strings. Is bind pretty much the same as map?

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

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)()
}

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

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

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

I think?

the implicitly method looks for an implicit value (value, right?) that implements Monad[Function0]. Where does this implicit definition come from? I’m guessing this is from the 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 bind (() => a.unsafePerformIO) seems to be a function that takes no parameters and returns a.unsafePerformIO. How should I read this? bind takes a container type as its first argument, so maybe () => a.unsafePerformIO resolves to a container type?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-25T16:04:37+00:00Added an answer on May 25, 2026 at 4:04 pm

    IO[A] is intended to represent an Action returning an A, where the result of the Action may depend on the environment (meaning anything, values of variables, file system, system time…) and the execution of the action may also modify the environment. Actually, scala type for an Action would be Function0. Function0[A] returns an A when called and it is certainly allowed to depend on and modify the environment. IO is Function0 under another name, but it is intended to distinguish (tag?) those Function0 which depends on the environment from the other ones, which are actually pure value (if you say f is a function[A] which always returns the same value, without any side effect, there is no much difference between f and its result). To be precise, it is not so much that function tagged as IO must have side effect. It is that those not so tagged must have none. Note however than wrapping impure functions in IO is entirely voluntary, there is no way you will have a guarantee when you get a Function0 that it is pure. Using IO is certainly not the dominant style in scala.

    pure takes a value and turns it into a value contained in the
    “container” type.

    Quite right, but “container” may mean quite a lot of things. And the one returned by pure must be as light as possible, it must be the one that makes no difference. The point of list is that they may have any number of values. The one returned by pure must have one. The point of IO is that it depends on and affect the environment. The one returned by pure must do no such thing. So it is actually the pure Function0 () => a, wrapped in IO.

    bind pretty much the same as map

    Not so, bind is the same as flatMap. As you write, map would receive a function from Int to String, but here you have the function from Int to List[String]

    Now, forget IO for a moment and consider what bind/flatMap would mean for an Action, that is for Function0.
    Let’s have

    val askUserForLineNumber: () => Int = {...}
    val readingLineAt: Int => Function0[String] = {i: Int  => () => ...}
    

    Now if we must combine, as bind/flatMap does, those items to get an action that returns a String, what it must be is pretty clear: ask the reader for the line number, read that line and returns it. That would be

    val askForLineNumberAndReadIt= () => {
      val lineNumber : Int = askUserForLineNumber()
      val readingRequiredLine: Function0[String] = readingLineAt(line)
      val lineContent= readingRequiredLine()
      lineContent
    }
    

    More generically

    def bind[A,B](a: Function0[A], f: A => Function0[B]) = () => {
      val value = a()
      val nextAction = f(value)
      val result = nextAction()
      result
    }
    

    And shorter:

    def bind[A,B](a: Function0[A], f: A => Function0[B]) 
      = () => {f(a())()}
    

    So we know what bind must be for Function0, pure is clear too. We can do

    object ActionMonad extends Monad[Function0] {
      def pure[A](a: => A) = () => a
      def bind[A,B](a: () => A, f: A => Function0[B]) = () => f(a())()
    }
    

    Now, IO is Function0 in disguise. Instead of just doing a(), we must do a.unsafePerformIO. And to define one, instead of () => body, we write IO {body}
    So there could be

    object IOMonad extends Monad[IO] {
      def pure[A](a: => A) = IO {a}
      def bind[A,B](a: IO[A], f: A => IO[B]) = IO {f(a.unsafePerformIO).unsafePerformIO}
    }
    

    In my view, that would be good enough. But in fact it repeats the ActionMonad. The point in the code you refer to is to avoid that and reuse what is done for Function0 instead. One goes easily from IO to Function0 (with () => io.unsafePerformIo) as well as from Function0 to IO (with IO { action() }). If you have f: A => IO[B], you can also change that to f: A => Function0[B], just by composing with the IO to Function0 transform, so (x: A) => f(x).unsafePerformIO.

    What happens here in the bind of IO is:

    1. () => a.unsafePerformIO: turn a into a Function0
    2. (x:A) => () => f(x).unsafePerformIO): turn f into an A => Function0[B]
    3. implicitly[Monad[Function0]]: get the default monad for Function0, the very same as the ActionMonad above
    4. bind(...): apply the bind of the Function0 monad to the arguments a and f that have just been converted to Function0
    5. The enclosing IO{...}: convert the result back to IO.

    (Not sure I like it much)

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

This is a follow-up of this question on here http://iphonedevelopment.blogspot.com/2010/02/drawing-hud-display-in-opengl-es.html It tackles on the
This is a followup to my question here . I would like to understand
This is a follow-up question from here . The code is working great, it
This is a followup question of How to encode characters from Oracle to Xml?
This is a follow up question from here . Where I want do go
Note, this is a follow up to my question here . I'm trying to
This is a follow up question from my previous one found here I need
This is a followup to the question I just asked here . I've created
this is a followup on my former question here . The resulting file which
As a follow-up to this question Here is some code that compiles and runs

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.