Take this simple bit of code:
var line = "";
do {
println("Please enter a non-empty line: ")
line = readLine()
} while (line.isEmpty())
println("You entered a non-empty line: " + line)
It's definitely not particularly elegant, especially with the unfortunate scoping of line
-- however, I think it's quite simple to read.
Now trying to translate this directly to scalaz effect, I have come up with:
def nonEmptyLine: IO[String] = for {
_ <- putStrLn("Please enter a non-empty line:")
line <- readLn
r <- if (line.isEmpty()) nonEmptyLine else IO(line)
} yield r
(for {
line <- nonEmptyLine
_ <- putStrLn("You entered a non-empty line: " + line)
} yield ()).unsafePerformIO
Which makes me feel like I'm missing something, as this doesn't feel like an improvement at all? Is there some higher order control flow stuff I'm missing?