All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.specs2.control.eff.StateEffect.scala Maven / Gradle / Ivy

The newest version!
package org.specs2.control.eff

import scalaz.syntax.monad._
import scalaz._
import Interpret._
import Eff._
import Effects.|:

/**
 * Effect for passing state along computations
 *
 * Several state effects can be used in the same stack if they are tagged
 *
 * Internally backed up by scalaz.State
 *
 */
trait StateEffect extends
  StateCreation with
  StateInterpretation with
  StateImplicits

object StateEffect extends StateEffect

trait StateCreation {

  /** store a new state value */
  def put[R, S](s: S)(implicit member: Member[({type l[X]=State[S, X]})#l, R]): Eff[R, Unit] =
    send[({type l[X]=State[S, X]})#l, R, Unit](State.put(s))

  /** get the current state value */
  def get[R, S](implicit member: Member[({type l[X]=State[S, X]})#l, R]): Eff[R, S] =
    send[({type l[X]=State[S, X]})#l, R, S](State.get)

  /** get the current state value and map it with a function f */
  def gets[R, S, T](f: S => T)(implicit member: Member[({type l[X]=State[S, X]})#l, R]): Eff[R, T] =
    send[({type l[X]=State[S, X]})#l, R, T](State.gets(f))

  /** modify the current state value */
  def modify[R, S](f: S => S)(implicit member: Member[({type l[X]=State[S, X]})#l, R]): Eff[R, Unit] =
    get >>= ((s: S) => put(f(s)))

  /** store a new state value */
  def putTagged[R, T, S](s: S)(implicit member: Member[({type l[X] = State[S, X] @@ T})#l, R]): Eff[R, Unit] =
    send[({type l[X] = State[S, X] @@ T})#l, R, Unit](Tag(State.put(s)))

  /** get the current state value */
  def getTagged[R, T, S](implicit member: Member[({type l[X] = State[S, X] @@ T})#l, R]): Eff[R, S] =
    send[({type l[X] = State[S, X] @@ T})#l, R, S](Tag(State.get))

  /** get the current state value and map it with a function f */
  def getsTagged[R, U, S, T](f: S => T)(implicit member: Member[({type l[X] = State[S, X] @@ U})#l, R]): Eff[R, T] =
    send[({type l[X] = State[S, X] @@ U})#l, R, T](Tag(State.gets(f)))

  /** modify the current state value */
  def modifyTagged[R, T, S](f: S => S)(implicit member: Member[({type l[X] = State[S, X] @@ T})#l, R]): Eff[R, Unit] =
    getTagged >>= ((s: S) => putTagged(f(s)))

}

object StateCreation extends StateCreation

trait StateInterpretation {
  /** run a state effect, with a Monoidal state */
  def evalStateZero[R <: Effects, U <: Effects, S : Monoid, A](w: Eff[R, A])(implicit m: Member.Aux[({type l[X]=State[S, X]})#l, R, U]): Eff[U, A] =
    evalState(Monoid[S].zero)(w)

  /** run a state effect, with an initial value, return only the value */
  def evalState[R <: Effects, U <: Effects, S, A](initial: S)(w: Eff[R, A])(implicit m: Member.Aux[({type l[X]=State[S, X]})#l, R, U]): Eff[U, A] =
    runState(initial)(w).map(_._1)

  /** run a state effect, with a monoidal state, return only the state */
  def execStateZero[R <: Effects, U <: Effects, S : Monoid, A](w: Eff[R, A])(implicit m: Member.Aux[({type l[X]=State[S, X]})#l, R, U]): Eff[U, S] =
    execState(Monoid[S].zero)(w)

  /** run a state effect, with an initial value, return only the state */
  def execState[R <: Effects, U <: Effects, S, A](initial: S)(w: Eff[R, A])(implicit m: Member.Aux[({type l[X]=State[S, X]})#l, R, U]): Eff[U, S] =
    runState(initial)(w).map(_._2)

  /** run a state effect, with an initial value */
  def runStateZero[R <: Effects, U <: Effects, S : Monoid, A](w: Eff[R, A])(implicit m: Member.Aux[({type l[X]=State[S, X]})#l, R, U]): Eff[U, (A, S)] =
    runState(Monoid[S].zero)(w)

  /** run a state effect, with an initial value */
  def runState[R <: Effects, U <: Effects, S1, A](initial: S1)(w: Eff[R, A])(implicit m: Member.Aux[({type l[X]=State[S1, X]})#l, R, U]): Eff[U, (A, S1)] = {
    val recurse: StateRecurse[({type l[X]=State[S1, X]})#l, A, (A, S1)] = new StateRecurse[({type l[X]=State[S1, X]})#l, A, (A, S1)] {

      type S = S1
      val init = initial

      def apply[X](x: State[S, X], s: S) =
        x.run(s).swap

      def finalize(a: A, s: S) = (a, s)

    }
    interpretState1[R, U, ({type l[X]=State[S1, X]})#l, A, (A, S1)]((a: A) => (a, initial))(recurse)(w)
  }

  /** run a state effect, with a Monoidal state */
  def evalStateZeroTagged[R <: Effects, U <: Effects, T, S : Monoid, A](w: Eff[R, A])(implicit m: Member.Aux[({type l[X] = State[S, X] @@ T})#l, R, U]): Eff[U, A] =
    evalStateTagged(Monoid[S].zero)(w)

  /** run a state effect, with an initial value, return only the value */
  def evalStateTagged[R <: Effects, U <: Effects, T, S, A](initial: S)(w: Eff[R, A])(implicit m: Member.Aux[({type l[X] = State[S, X] @@ T})#l, R, U]): Eff[U, A] =
    runStateTagged(initial)(w).map(_._1)

  /** run a state effect, with a monoidal state, return only the state */
  def execStateZeroTagged[R <: Effects, U <: Effects, T, S : Monoid, A](w: Eff[R, A])(implicit m: Member.Aux[({type l[X] = State[S, X] @@ T})#l, R, U]): Eff[U, S] =
    execStateTagged(Monoid[S].zero)(w)

  /** run a state effect, with an initial value, return only the state */
  def execStateTagged[R <: Effects, U <: Effects, T, S, A](initial: S)(w: Eff[R, A])(implicit m: Member.Aux[({type l[X] = State[S, X] @@ T})#l, R, U]): Eff[U, S] =
    runStateTagged(initial)(w).map(_._2)

  /** run a state effect, with an initial value */
  def runStateZeroTagged[R <: Effects, U <: Effects, T, S : Monoid, A](w: Eff[R, A])(implicit m: Member.Aux[({type l[X] = State[S, X] @@ T})#l, R, U]): Eff[U, (A, S)] =
    runStateTagged(Monoid[S].zero)(w)

  /** run a tagged state effect, with an initial value */
  def runStateTagged[R <: Effects, U <: Effects, T, S1, A](initial: S1)(w: Eff[R, A])(implicit m: Member.Aux[({type l[X] = State[S1, X] @@ T})#l, R, U]): Eff[U, (A, S1)] = {
    type SS[X] = State[S1, X] @@ T

    val recurse: StateRecurse[SS, A, (A, S1)] = new StateRecurse[SS, A, (A, S1)] {
      type S = S1
      val init = initial

      def apply[X](x: State[S, X] @@ T, s: S) =
        Tag.unwrap(x).run(s).swap

      def finalize(a: A, s: S) = (a, s)

    }

    interpretState1[R, U, SS, A, (A, S1)]((a: A) => (a, initial))(recurse)(w)
  }

  /**
   * Lift a computation over a "small" state (for a subsystem) into
   * a computation over a "bigger" state (for the full application state)
   */
  def lensState[TS, SS, U, T, S, A](state: Eff[TS, A], getter: S => T, setter: (S, T) => S)
                                   (implicit ts: Member.Aux[({type l[X]=State[T, X]})#l, TS, U], ss: Member.Aux[({type l[X]=State[S, X]})#l, SS, U]): Eff[SS, A] =
    Interpret.transform[TS, SS, U, ({type l[X]=State[T, X]})#l, ({type l[X]=State[S, X]})#l, A](state, new ~>[({type l[X]=State[T, X]})#l, ({type l[X]=State[S, X]})#l] {
      def apply[X](tstate: State[T, X]): State[S, X] =
        State { s: S =>
          val (t, x) = tstate.run(getter(s))
          (setter(s, t), x)
        }
    })

}

object StateInterpretation extends StateInterpretation

trait StateImplicits extends StateImplicits1 {
  implicit def TaggedStateMemberZero[Tg, A]: Member.Aux[({type l[X] = State[A, X] @@ Tg})#l, ({type l[X] = State[A, X] @@ Tg})#l |: NoEffect, NoEffect] = {
    type T[X] = State[A, X] @@ Tg
    Member.zero[T]
  }

  implicit def TaggedStateMemberFirst[R <: Effects, Tg, A]: Member.Aux[({type l[X] = State[A, X] @@ Tg})#l, ({type l[X] = State[A, X] @@ Tg})#l |: R, R] = {
    type T[X] = State[A, X] @@ Tg
    Member.first[T, R]
  }

}
trait StateImplicits1 {
  implicit def TaggedStateMemberSuccessor[O[_], R <: Effects, U <: Effects, Tg, A](implicit m: Member.Aux[({type l[X] = State[A, X] @@ Tg})#l, R, U]): Member.Aux[({type l[X] = State[A, X] @@ Tg})#l, O |: R, O |: U] = {
    type T[X] = State[A, X] @@ Tg
    Member.successor[T, O, R, U]
  }

}

object StateImplicits extends StateImplicits





© 2015 - 2024 Weber Informatics LLC | Privacy Policy