Last active
August 29, 2015 14:23
-
-
Save hhanh00/a63565094a69643aa532 to your computer and use it in GitHub Desktop.
Multi level lens with scalaz
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._ | |
case class Valuation(realized: BigDecimal, unrealized: BigDecimal) { | |
def addR(r: BigDecimal) = this copy (realized = this.realized+r) | |
def addU(u: BigDecimal) = this copy (unrealized = this.unrealized+u) | |
} | |
object Valuation { | |
def apply() = new Valuation(0, 0) | |
} | |
case class Holding(symbol: String, quantity: Int, valuation: Valuation) | |
object Holding { | |
def default(symbol: String) = new Holding(symbol, 1, Valuation()) // give 1 share for free! | |
} | |
case class Portfolio(user: String, holdings: Map[String, Holding], valuation: Valuation) | |
case class Global(portfolios: Map[String, Portfolio], valuation: Valuation) | |
object Hello extends App { | |
val g = Global(Map.empty, Valuation()) | |
def globalL(user: String) = Lens.lensu[Global, Portfolio]((g, p) => g copy (portfolios = g.portfolios.updated(user, p)), _.portfolios.getOrElse(user, Portfolio(user, Map.empty, Valuation()))) | |
val globalValuationL = Lens.lensu[Global, Valuation]((p, v) => p copy (valuation = v), _.valuation) | |
def portfolioL(symbol: String) = Lens.lensu[Portfolio, Holding]((p, h) => p copy (holdings = p.holdings.updated(symbol, h)), _.holdings.getOrElse(symbol, Holding.default(symbol))) | |
val portfolioValuationL = Lens.lensu[Portfolio, Valuation]((p, v) => p copy (valuation = v), _.valuation) | |
val holdingL = Lens.lensu[Holding, Valuation]((h, v) => h copy (valuation = v), _.valuation) | |
def applyValuationMod(user: String, symbol: String)(f: Valuation => Valuation) = { | |
val h = globalL(user) >=> portfolioL(symbol) >=> holdingL | |
val p = globalL(user) >=> portfolioValuationL | |
val g = globalValuationL | |
List(h, p, g) map(_ =>= f) reduceLeft (_ andThen _) | |
} | |
def applyMark(symbol: String)(markFunc: Holding => Valuation) = { (global: Global) => | |
global.portfolios.foldLeft(global) { case (g, (user, pf)) => | |
val f = pf.holdings.get(symbol) map (h => (valuation: Valuation) => valuation.addU(markFunc(h).unrealized - h.valuation.unrealized)) | |
(f map (fv => applyValuationMod(user, symbol)(fv)) getOrElse identity[Global] _)(g) | |
} | |
} | |
def applyValuationModOnSymbol(symbol: String)(f: Valuation => Valuation) = { (global: Global) => | |
global.portfolios.keys.foldLeft(global)((g, user) => applyValuationMod(user, symbol)(f)(g)) | |
} | |
val f = applyValuationMod("h", "IBM")(_ addR 10.5) andThen applyValuationMod("h", "MSFT")(_ addR 11.5) andThen applyValuationMod("c", "AAPL")(_ addU -10.0) | |
val g2 = f(g) | |
println(g2) | |
val mark = (h: Holding) => Valuation(0, h.quantity*100) | |
println(applyMark("IBM")(mark)(g2)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment