Skip to content

Instantly share code, notes, and snippets.

@travisbrown
Forked from kevinmeredith/MonadADT.scala
Last active April 28, 2017 02:34

Revisions

  1. travisbrown revised this gist Jul 24, 2015. 1 changed file with 3 additions and 10 deletions.
    13 changes: 3 additions & 10 deletions indexed-example.scala
    Original file line number Diff line number Diff line change
    @@ -7,16 +7,9 @@ case object Third extends Status

    type StringOr[A] = String \/ A

    def f = IndexedStateT.constantIndexedStateT[StringOr, Unit, First.type, Unit](
    ()
    )(First)

    def g = IndexedStateT[StringOr, First.type, Second.type, Unit](s =>
    (Second, ()).right
    )
    def h = IndexedStateT[StringOr, Second.type, Third.type, Unit](s =>
    (Third, ()).right
    )
    def f = IndexedStateT.constantIndexedStateT[StringOr, Unit, First.type, Unit](())(First)
    def g = IndexedStateT[StringOr, First.type, Second.type, Unit](_ => (Second, ()).right)
    def h = IndexedStateT[StringOr, Second.type, Third.type, Unit](_ => (Third, ()).right)

    for {
    a <- f
  2. travisbrown revised this gist Jul 24, 2015. 1 changed file with 34 additions and 0 deletions.
    34 changes: 34 additions & 0 deletions indexed-example.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,34 @@
    import scalaz._, Scalaz._

    sealed trait Status
    case object First extends Status
    case object Second extends Status
    case object Third extends Status

    type StringOr[A] = String \/ A

    def f = IndexedStateT.constantIndexedStateT[StringOr, Unit, First.type, Unit](
    ()
    )(First)

    def g = IndexedStateT[StringOr, First.type, Second.type, Unit](s =>
    (Second, ()).right
    )
    def h = IndexedStateT[StringOr, Second.type, Third.type, Unit](s =>
    (Third, ()).right
    )

    for {
    a <- f
    b <- g
    c <- h
    } yield c

    /* Doesn't compile:
    for {
    a <- g
    b <- f
    c <- h
    } yield c
    */

  3. @kevinmeredith kevinmeredith revised this gist Jul 23, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions MonadADT.scala
    Original file line number Diff line number Diff line change
    @@ -29,7 +29,7 @@ res4: scala.util.Either[String,Status] = Right(Three)
    // 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 in this model,
    // but I'm finding myself adding tests (with a test service)
    // 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.")
  4. @kevinmeredith kevinmeredith revised this gist Jul 23, 2015. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion MonadADT.scala
    Original file line number Diff line number Diff line change
    @@ -29,4 +29,7 @@ res4: scala.util.Either[String,Status] = Right(Three)
    // 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?
    // Can I do better here? I wrote a service in this model,
    // 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.")
  5. @kevinmeredith kevinmeredith created this gist Jul 23, 2015.
    32 changes: 32 additions & 0 deletions MonadADT.scala
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,32 @@
    // 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?