5

拿这个简单的代码:

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

这让我觉得我错过了一些东西,因为这根本不像是一种改进?我缺少一些更高阶的控制流吗?

4

1 回答 1

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比直接的命令式解决方案更简洁或更容易阅读。

于 2013-04-13T20:01:04.250 回答