Use only value from IO monad without use-case I / O

Carrying out some kind of home project, I came across an interesting effect, which now seems obvious to me, but still I see no way to get away from it. This is the point (I am using ScalaZ, but in haskell there will probably be the same result):

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)
}

When I try to get input from core, askAndReadResponseevaluates twice - once to evaluate the condition, and then to ifM(so I have a message and readLnagain, then necessary). What I need is only a verified value (for example, for printing later)

Is there any elegant way to do this, in particular, to pass on the I / O result without previous I / O, namely to avoid executing askAndReadResponsetwice?

+4
1

, flatMap:

def core: IO[String] = askAndReadResponse("enter something").flatMap {
  case response if response.length > 2 => response.point[IO]
  case response => core
}

( ) ( , , - ).

ifM - , .

+6

Source: https://habr.com/ru/post/1611324/


All Articles