仅使用来自 IO monad 的值,没有先例 IO 操作
Use only the value from IO monad without precedent IO actions
在做一些家庭项目时,我遇到了一个有趣的效果,现在对我来说似乎很明显,但我仍然没有找到摆脱它的方法。
这就是要点(我正在使用 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
中(所以我得到消息和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
}
这让你可以获取一次计算的结果(用户在提示后输入文本)并在后续计算中使用它(关于是否 return 或循环的计算,结果如果 returning).
ifM
对你的情况没有用——只有当你的条件和成功的分支是独立计算时它才会在这里起作用。
在做一些家庭项目时,我遇到了一个有趣的效果,现在对我来说似乎很明显,但我仍然没有找到摆脱它的方法。 这就是要点(我正在使用 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
中(所以我得到消息和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
}
这让你可以获取一次计算的结果(用户在提示后输入文本)并在后续计算中使用它(关于是否 return 或循环的计算,结果如果 returning).
ifM
对你的情况没有用——只有当你的条件和成功的分支是独立计算时它才会在这里起作用。