Skip to content

Instantly share code, notes, and snippets.

@maliqq
Forked from channingwalton/StateMonad.scala
Created December 2, 2016 02:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maliqq/185d100c6bad9c09bf37408d887cb96c to your computer and use it in GitHub Desktop.
Save maliqq/185d100c6bad9c09bf37408d887cb96c to your computer and use it in GitHub Desktop.
State Monad and Validation with Scalaz
import scalaz._
import Scalaz._
/**
* Use the state monad to 'process a trade' and store the new trade.
* As well as processing the trade, handle validation errors.
*/
object StateMonad extends App {
case class Trade(info: String)
type Store = List[Trade]
// a function that takes a new trade and processes it yielding new state and validation
val newTrade = (newTrade: Trade) ⇒
for (
_ ← log("New Trade");
accepted ← accept(newTrade);
_ ← log("Hedging New Trade");
hedged ← hedge(newTrade);
_ ← log("Validating portfolio");
portfolio ← validatePortfolio;
_ ← log("New trade processed")
) yield (accepted.liftFailNel |@| hedged.liftFailNel |@| portfolio.liftFailNel) {_ + _ + _}
println("Haven't done anything yet!")
// assume some existing state
var globalState: Store = Nil
// exercise the newTrade function with the existing state
val (newState, validation) = newTrade(Trade("Big Trade"))(globalState)
// assign the new state to our global state if the validation says its ok
globalState = validation.fold(failures ⇒ { println(failures); globalState }, msg ⇒ newState)
println("Store contains " + globalState)
// does nothing but print a messages and return the state its given
def log(m: String) = state[Store, Unit](s ⇒ (s, println(m)))
// accepts a trade putting it into the store
def accept(newTrade: Trade) = state[Store, Validation[String, String]](s ⇒ (newTrade :: s, "trade accepted".success))
// hedge against the new trade - apparently its all the rage
def hedge(against: Trade) = state[Store, Validation[String, String]](s ⇒ (Trade("Hedge Trade against " + against) :: s, "hedge trade step".success))
// validate the portfolio doing nothing with the state
def validatePortfolio = state[Store, Validation[String, String]](s ⇒ {
if (s.size > 10) (s, "Portolio is too big".fail)
else (s, "All ok".success)
})
}
/*
Running this produces:
Haven't done anything yet!
New Trade
Hedging New Trade
Validating portfolio
New trade processed
Store contains List(Trade(Hedge Trade against Trade(Big Trade)), Trade(Big Trade))
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment