仅使用IO monad中没有先例IO操作的值

时间:2015-10-12 18:37:13

标签: scala io monads scalaz

做一些家庭项目,我遇到了一个感兴趣的效果,现在,对我来说似乎很明显,但我仍然没有办法摆脱它。 这就是要点(我使用的是ScalaZ,但在haskell中可能会有相同的结果):

def askAndReadResponse(question: String): IO[String] = {
  putStrLn(question) >> readLn
}

def core: IO[String] = {
  val answer: IO[String] = askAndReadResponse("enter something")
  val cond: IO[Boolean] = answer map {_.length > 2}
  IO.ioMonad.ifM(cond, answer, core)
}

当我尝试从core获取输入时,askAndReadResponse评估两次 - 一次用于评估条件,然后在ifM中(所以我有消息和{{ 1}}再一次必要的时间)。 我需要的 - 只是验证的值(例如,稍后打印)

是否有任何优雅的方法可以做到这一点,特别是 - 在没有先前的IO操作的情况下进一步传递IO的结果,即避免执行readLn两次?

1 个答案:

答案 0 :(得分:6)

您可以使用client.CreateDocumentQuery<A1>(collectionLink).Where(d => d.DataType == "A1" && d.x == "xvaluefilter")

的monadic绑定对效果进行排序
flatMap

这使您可以获取一次计算的结果(用户在提示后输入文本)并在后续计算中使用它(关于是否返回或循环的计算,以及返回时的结果)。

def core: IO[String] = askAndReadResponse("enter something").flatMap { case response if response.length > 2 => response.point[IO] case response => core } 在你的情况下不会有用 - 如果你的条件和成功的分支都是独立的计算,它只能在这里工作。