Advertisement
Guest User

Monad.scala

a guest
Oct 23rd, 2014
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 4.01 KB | None | 0 0
  1. /**
  2.  *
  3.  */
  4. /**
  5.  * @author jan.sulmont
  6.  *
  7.  */
  8. object StateMonad {
  9.   import State._
  10.  
  11.   trait State[S, +A] {
  12.     def apply(s: S): (S, A)
  13.     def map[B](f: A => B): State[S, B] = state(apply(_) match {
  14.       case (s, a) => (s, f(a))
  15.     })
  16.  
  17.     def flatMap[B](f: A => State[S, B]): State[S, B] = state(apply(_) match {
  18.       case (s, a) => f(a)(s)
  19.     })
  20.   }
  21.  
  22.   object State {
  23.     def state[S, A](f: S => (S, A)) = new State[S, A] {
  24.       def apply(s: S) = f(s)
  25.     }    
  26.     def init[S]: State[S, S] = state[S, S](s => (s, s))  
  27.     def modify[S](f: S => S) = init[S] flatMap (s => state(_ => (f(s), ())))
  28.     def gets[S,A](f: S => A): State[S, A] = init[S] flatMap (s => state(_ => (s, f(s))))
  29.       // for (s <- init) yield f(s)
  30.   }
  31. }
  32.  
  33. object PriceCalculator {
  34.   object Stubs {
  35.     def findTheBasePrice(productId: String) = 10.0
  36.     def findStateSpecificDiscount(productId: String, stateCode: String) = 0.5
  37.     def findProductSpecificDiscount(productId: String) = 0.5
  38.     def calculateTax(productId: String, price: Double) = 5.0
  39.   }
  40.   import Stubs._
  41.   import StateMonad.State._
  42.   case class PriceState(productId: String, stateCode: String,price: Double)
  43.  
  44.   def findBasePrice(ps: PriceState): Double = {
  45.     val basePrice = findTheBasePrice(ps.productId)
  46.     basePrice
  47.   }
  48.  
  49.   def applyStateSpecificDiscount(ps: PriceState): Double = {
  50.     val discount = findStateSpecificDiscount(ps.productId, ps.stateCode)
  51.     ps.price - discount
  52.   }
  53.  
  54.   def applyProductSpecificDiscount(ps: PriceState): Double = {
  55.     val discount = findProductSpecificDiscount(ps.productId)
  56.     ps.price - discount
  57.   }  
  58.   def applyTax(ps: PriceState): Double = {
  59.     val tax = calculateTax(ps.productId, ps.price)
  60.     ps.price + tax
  61.   }
  62.  
  63.   def calculatePrice2(productId: String, stateCode: String): Double = {  
  64.     def modifyPriceState(f: PriceState => Double) = modify[PriceState](s => s.copy(price = f(s)))
  65.     val stateMonad = modifyPriceState(findBasePrice) flatMap {a =>
  66.       modifyPriceState(applyStateSpecificDiscount) flatMap {b =>
  67.         modifyPriceState(applyProductSpecificDiscount) flatMap {c =>
  68.           modifyPriceState(applyTax) map {d =>() }
  69.         }
  70.       }
  71.     }
  72.     val initialPriceState = PriceState(productId, stateCode, 0.0)  
  73.     val finalPriceState = stateMonad.apply(initialPriceState)._1
  74.     val finalPrice = finalPriceState.price
  75.     finalPrice
  76.   }
  77.    
  78.  
  79.   def calculatePrice(productId: String, stateCode: String): Double = {  
  80.     def modifyPriceState(f: PriceState => Double) = modify[PriceState](s => s.copy(price = f(s)))
  81.     val stateMonad = for {
  82.         _ <- modifyPriceState(findBasePrice)
  83.         _ <- modifyPriceState(applyStateSpecificDiscount)
  84.         _ <- modifyPriceState(applyProductSpecificDiscount)
  85.         _ <- modifyPriceState(applyTax)
  86.       } yield ()
  87.     val initialPriceState = PriceState(productId, stateCode, 0.0)  
  88.     val finalPriceState = stateMonad.apply(initialPriceState)._1
  89.     val finalPrice = finalPriceState.price
  90.     finalPrice
  91.   }
  92.    
  93.   def calculatePriceWithLog(productId: String, stateCode: String): Double = {  
  94.     def modifyPriceState(f: PriceState => Double) = modify[PriceState](s => s.copy(price = f(s)))
  95.     def logStep(f: PriceState => String) = gets(f)
  96.     val stateMonad = for {
  97.         _ <- modifyPriceState(findBasePrice)
  98.         a <- logStep(s => "Base Price " + s)
  99.         _ <- modifyPriceState(applyStateSpecificDiscount)
  100.         b <- logStep(s => "After state discount " + s)
  101.         _ <- modifyPriceState(applyProductSpecificDiscount)
  102.         c <- logStep(s => "After product discount " + s)
  103.         _ <- modifyPriceState(applyTax)
  104.         d <- logStep(s => "After tax " + s)
  105.       } yield a :: b :: c :: d :: Nil
  106.     val (finalPriceState, log) = stateMonad.apply(PriceState(productId, stateCode, 0.0))
  107.     println(">>>>>>>>> " + finalPriceState.price)
  108.     println("log " + log)
  109.     finalPriceState.price
  110.   }
  111.  
  112. }
  113.  
  114.  
  115.  
  116. object M extends App {
  117.   println(PriceCalculator.calculatePriceWithLog("1234", "4321"))
  118. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement