Skip to content

Instantly share code, notes, and snippets.

@aappddeevv
Created September 15, 2013 13:07
Show Gist options
  • Save aappddeevv/6570612 to your computer and use it in GitHub Desktop.
Save aappddeevv/6570612 to your computer and use it in GitHub Desktop.
import scalaz._
import scalaz.State._
case class Session(version: Int = 0)
// Create a new output string and increment session version.
def func1(arg: String) = State((x: Session) => (x.copy(version = x.version + 1), arg + "-" + x.version))
val composedFunction1: State[Session, String] = for {
// Because we gave this val an explicit type, init does not need the type specification
_ <- init
// Increment the state and return state+value. Essentially, throw away the value.
_ <- func1("joe")
// Modify the state directly.
_ <- modify { s: Session => Session(100) }
// Increment the state and return state+value. Essentially, throw away the value.
_ <- func1("alice")
// Modify the state directly again!
_ <- put(Session(200))
// Increment the state and return state+value. Keep the value this time.
x <- func1("nathan")
} yield x
println("composedFunction1: " + composedFunction1(Session(0)))
// Now create a composition where the returned value changes. Since the returned
// value does not really matter when the state propagates (the state needs to be the
// same between for steps or have conversions available) so the returned value can
// change each step of the way.
def funcReturnInt(arg: String): State[Session, Int] =
State((x: Session) => (x.copy(version=x.version+1), arg.toInt))
def funcReturnString(arg: String): State[Session, String] =
State((x: Session) => (x.copy(version=x.version+1), arg + "-" + x.version))
val composedFunction2 = for {
// by using put first, we effectively ignore any input value
_ <- put(Session(0))
_ <- func1("joe")
_ <- funcReturnInt("30")
x <- funcReturnString("alice")
} yield x
// Null is used because we have to call the composed function with
// an argument. null is used for illustration purposes.
println("composedFunction2: " + composedFunction2(null))
// We can also compose the two composed functions together. We explicitly
// make the type known (State[Session, String]) for illustration purposes
// but the compiler can figure it out on its own.
def composedFunction1and2 = for {
// Put the argument given by the programmer function into a state object
_ <- init[Session]
_ <- composedFunction1
x <- composedFunction2
} yield x
// Since composedFunction2 resets the state at the start of its function,
// we should expect the saem result as composedFunction2.
println("composedFunction1and2: " + composedFunction1and2(Session(0)))
/** Prints:
composedFunction1: (Session(201),nathan-200)
composedFunction2: (Session(3),alice-2)
composedFunction1and2: (Session(3),alice-2)
**/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment