csci3155

CSCI3155 Coursework
git clone https://git.pngu.org/csci3155
Log | Files | Refs | README

DoWith.scala (912B)


package jsy.util

/*
 * DoWith is a data structure that holds a function that returns a result of
 * type R with a input-output state of type W.
 *
 * Aside: This is also known as the State monad.
 */
sealed class DoWith[W,+R] private (doer: W => (W,R)) {
  def apply(w: W) = doer(w)

  def map[B](f: R => B): DoWith[W,B] = new DoWith[W,B]({
    (w: W) => {
      val (wp, r) = doer(w)
      (wp, f(r))
    }
  })

  def flatMap[B](f: R => DoWith[W,B]): DoWith[W,B] = new DoWith[W,B]({
    (w: W) => {
      val (wp, r) = doer(w)
      f(r)(wp) // same as f(a).apply(s)
    }
  })
}

object DoWith {
  def doget[W]: DoWith[W, W] = new DoWith[W, W]({ w => (w, w) })
  def doput[W](w: W): DoWith[W, Unit] = new DoWith[W, Unit]({ _ => (w, ()) })
  def doreturn[W, R](r: R): DoWith[W, R] = new DoWith[W, R]({ w => (w, r) })
  def domodify[W](f: W => W): DoWith[W, Unit] = new DoWith[W, Unit]({ w => (f(w), ()) })
}