I S*_*ces 4 io monads scala 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)
}
Run Code Online (Sandbox Code Playgroud)
当我试图从中获取输入时core,askAndReadResponse评估两次 - 一次用于评估条件,然后用于ifM(因此我有消息,readLn然后再需要一次).我需要什么 - 只是验证的值(例如,稍后打印)
有没有优雅的方法来做到这一点,特别是 - 进一步传递IO的结果,没有先前的IO动作,即避免执行 askAndReadResponse两次?
您可以使用monadic绑定对效果进行排序flatMap:
def core: IO[String] = askAndReadResponse("enter something").flatMap {
case response if response.length > 2 => response.point[IO]
case response => core
}
Run Code Online (Sandbox Code Playgroud)
这使您可以获取一次计算的结果(用户在提示后输入文本)并在后续计算中使用它(关于是返回还是循环的计算,以及返回时的结果).
ifM 只是在你的情况下不会有用 - 如果你的条件和成功的分支是独立的计算,它只会在这里工作.