Domanda

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?

È stato utile?

Soluzione

You can make this (at least arguably) a lot prettier by skipping the for notation and using the combinators *> and >>= to pipe everything together:

import scalaz._, Scalaz._, effect._, IO._

val prompt = putStrLn("Please enter a non-empty line:")

def report(line: String) = putStrLn("You entered a non-empty line: " + line)

def nonEmptyLine: IO[String] = prompt *> readLn >>= (
  (line: String) => if (line.isEmpty) nonEmptyLine else line.point[IO]
)

And then:

scala> (nonEmptyLine >>= report).unsafePerformIO
Please enter a non-empty line:
You entered a non-empty line: This is a test.

In general, though, I'm not sure you should expect code written using scalaz.effect to be more concise or easier to read than a straightforward imperative solution.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top