Skip to content

Instantly share code, notes, and snippets.

@noelwelsh
Created October 15, 2015 16:18
Show Gist options
  • Save noelwelsh/2b27272573c0e5294bb4 to your computer and use it in GitHub Desktop.
Save noelwelsh/2b27272573c0e5294bb4 to your computer and use it in GitHub Desktop.
Example of monadic loop using the State monad in Cats
import cats.{Id,Monad}
import cats.state.State
import cats.std.function._
import scala.language.higherKinds._
// Call Example.example.run to see the example running
object Example {
type MyState[A] = State[Int, A]
// A simple counter using the state monad. The counter counts down by one each
// iteration, and when it hits zero it stops. The value (Option[Int])
// indicates if we should continue or stop processing.
def extractNextItem: MyState[Option[Int]] =
State { counter =>
if(counter == 0)
(0, None)
else
(counter-1, Some(counter))
}
// Process the input and indicate if we should continue processing
def process(in: Option[Int]): Boolean =
in match {
case None => false
case Some(x) =>
println(s"Value is $x")
true
}
// Loop until the condition is false
def loop(in: MyState[Boolean]): MyState[Boolean] = {
val choice: MyState[Boolean] = extractNextItem map process
choice flatMap { bool =>
if(bool)
loop(choice)
else
choice
}
}
def example =
loop(extractNextItem map process).run(5)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment