Skip to content

Instantly share code, notes, and snippets.

@kevinmeredith
Last active August 29, 2015 14:25
Show Gist options
  • Save kevinmeredith/97ee6e8e23130956bea3 to your computer and use it in GitHub Desktop.
Save kevinmeredith/97ee6e8e23130956bea3 to your computer and use it in GitHub Desktop.
Sequencing through Monad with ADT
// Given the following ADT:
sealed trait Status
case object One extends Status
case object Two extends Status
case object Three extends Status
// They represent states. The natural progression, for this
// example, is : One -> Two -> Three
// Then, the functions that'll be used in the below monadic chaining.
// Observe that, it's possible, for an error to occur during f, g, or h
def f: Either[String, Status] = Right(One)
def g(x: Status): Either[String, Status] = Right(Two)
def h(x: Status): Either[String, Status] = Right(Three)
// Lastly, a for-comprehension that sequences through f, g and h.
// Please ignore the fact that g and h both discard their input
scala> for {
| a <- f.right
| b <- g(a).right
| c <- h(b).right
| } yield c
res4: scala.util.Either[String,Status] = Right(Three)
// From a type perspectice, `g` could return `Right(One)`. It would not
// make sense per this domain (where all we know is One -> Two -> Three),
// but of course One, Two and Three constitute Status.
// Can I do better here? I wrote a service that's similar to
// this example, but I'm finding myself adding tests (with a test service)
// where `g` returns Right(One). As a result, `h` will return
// Left("Invalid state. Got One, but expected Two.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment