拿一下这段简单的代码:
var line = "";
do {
println("Please enter a non-empty line: ")
line = readLine()
} while (line.isEmpty())
println("You entered a non-empty line: " + line)
这绝对不是特别优雅,尤其是line
的不幸范围 - 但是,我觉得这很简单。
现在尝试将其直接转换为scalaz效果,我想出了:
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
这让我觉得我错过了什么,因为这根本不是一种改善?我缺少一些更高阶的控制流程吗?
答案 0 :(得分:3)
您可以跳过for
符号并使用组合器*>
和>>=
将所有内容组合在一起,从而使这个(至少可以说是)更漂亮:
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]
)
然后:
scala> (nonEmptyLine >>= report).unsafePerformIO
Please enter a non-empty line:
You entered a non-empty line: This is a test.
但是,一般情况下,我不确定您是否应该期望使用scalaz.effect
编写的代码比简单的命令式解决方案更简洁或更易于阅读。