Created
September 15, 2013 13:07
-
-
Save aappddeevv/6570612 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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