Reputation: 41919
Looking at an IO Monad
example from Functional Programming in Scala, I created an SBT project to test out IO.scala
:
def ReadLine: IO[String] = IO { readLine }
def PrintLine(msg: String): IO[Unit] = IO { println(msg) }
def converter: IO[Unit] = for {
_ <- PrintLine("Enter a temperature in degrees fahrenheit: ")
d <- ReadLine.map(_.toDouble)
_ <- PrintLine(fahrenheitToCelsius(d).toString)
} yield ()
But, when I run console
from SBT to access the above class with REPL, I tried:
scala> val echo = Util.ReadLine.flatMap(Util.PrintLine)
echo: common.I01.IO[Unit] = common.I01$IO$$anon$2@71c6b580
I'm expecting to be prompted for typing in text (via readLine
), but I see, as I understand, simply an anonymous function/class.
How can I test out the above code?
Upvotes: 1
Views: 243
Reputation: 3855
Calling flatMap
on ReadLine
just produces an IO[Unit]
value that has not been interpreted. At some point, you have to call IO#run
(or IO#unsafePerformIO
in scalaz) to make the side effects happen
To preserve referential transparency, the general idea is to build up an IO[A]
(where A
is typically Unit
) and at the "outermost" part of your program, call run
on the value -- for example, from the main entry point of the application. That's not always easy/possible though depending on the environment you are running in -- e.g., some form of framework or container.
Because loss of referential transparency is generally considered a pretty serious disadvantage, it is common to defer running of the IO
value as long as possible. Hence, it is common to say that IO
is evaluated at the end of the universe.
In this case, the end of the universe is the REPL session, so try calling echo.run
from the REPL.
Upvotes: 1