alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (ST.scala)

This example Scala source code file (ST.scala) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Scala by Example" TM.

Learn more about this Scala project at its project page.

Java - Scala tags/keywords

classtag, immutablearray, int, starray, stref, strefinstances, tower, unit

The ST.scala Scala example source code

package scalaz
package effect

import reflect.ClassTag

import IvoryTower._
import STRef._
import STArray._
import ST._
import std.function._
import Id._

/**Mutable variable in state thread S containing a value of type A. [[http://research.microsoft.com/en-us/um/people/simonpj/papers/lazy-functional-state-threads.ps.Z]] */
sealed abstract class STRef[S, A] {
  protected var value: A

  /**Reads the value pointed at by this reference. */
  def read: ST[S, A] = returnST(value)

  /**Modifies the value at this reference with the given function. */
  def mod[B](f: A => A): ST[S, STRef[S, A]] = st((s: Tower[S]) => {
    value = f(value);
    (s, this)
  })

  /**Associates this reference with the given value. */
  def write(a: => A): ST[S, STRef[S, A]] = st((s: Tower[S]) => {
    value = a;
    (s, this)
  })

  /**Synonym for write*/
  def |=(a: => A): ST[S, STRef[S, A]] =
    write(a)

  /**Swap the value at this reference with the value at another. */
  def swap(that: STRef[S, A]): ST[S, Unit] = for {
    v1 <- this.read
    v2 <- that.read
    _ <- this write v2
    _ <- that write v1
  } yield ()
}

object STRef extends STRefInstances {

  def apply[S]: (Id ~> STRef[S, ?]) =
    stRef[S]

  def stRef[S]: (Id ~> STRef[S, ?]) = new (Id ~> STRef[S, ?]) {
    def apply[A](a: A) = new STRef[S, A] {
      var value = a
    }
  }
}

sealed abstract class STRefInstances {

  /**Equality for STRefs is reference equality */
  implicit def STRefEqual[S, A]: Equal[STRef[S, A]] =
    Equal.equalA // todo reference equality?
}

/**Mutable array in state thread S containing values of type A. */
sealed abstract class STArray[S, A] {
  def size: Int
  def z: A
  implicit def tag: ClassTag[A]

  private[this] val arr = Need(Array.fill(size)(z))

  private def value: Array[A] = arr.value

  import ST._

  /**Reads the value at the given index. */
  def read(i: Int): ST[S, A] = returnST(value(i))

  /**Writes the given value to the array, at the given offset. */
  def write(i: Int, a: A): ST[S, STArray[S, A]] = st(s => {
    value(i) = a;
    (s, this)
  })

  /**Turns a mutable array into an immutable one which is safe to return. */
  def freeze: ST[S, ImmutableArray[A]] = st(s => (s, ImmutableArray.fromArray(value)))

  /**Fill this array from the given association list. */
  def fill[B](f: (A, B) => A, xs: Traversable[(Int, B)]): ST[S, Unit] = xs match {
    case Nil             => returnST(())
    case ((i, v) :: ivs) => for {
      _ <- update(f, i, v)
      _ <- fill(f, ivs)
    } yield ()
  }

  /**Combine the given value with the value at the given index, using the given function. */
  def update[B](f: (A, B) => A, i: Int, v: B) = for {
    x <- read(i)
    _ <- write(i, f(x, v))
  } yield ()
}

object STArray {
  def apply[S, A : ClassTag](s: Int, a: A): STArray[S, A] = stArray(s, a)

  def stArray[S, A](s: Int, a: A)(implicit t: ClassTag[A]): STArray[S, A] = new STArray[S, A] {
    val size = s
    val z = a
    implicit val tag = t
  }
}

/**
 * Purely functional mutable state threads.
 * Based on JL and SPJ's paper "Lazy Functional State Threads"
 */
sealed abstract class ST[S, A] {
  private[effect] def apply(s: Tower[S]): (Tower[S], A)

  import ST._

  def flatMap[B](g: A => ST[S, B]): ST[S, B] =
    st(s => apply(s) match {
      case (ns, a) => g(a)(ns)
    })

  def map[B](g: A => B): ST[S, B] =
    st(s => apply(s) match {
      case (ns, a) => (ns, g(a))
    })
}

object ST extends STInstances {
  def apply[S, A](a: => A): ST[S, A] =
    returnST(a)

  def st[S, A](f: Tower[S] => (Tower[S], A)): ST[S, A] = new ST[S, A] {
    private[effect] def apply(s: Tower[S]) = f(s)
  }

  // Implicit conversions between IO and ST
  implicit def STToIO[A](st: ST[IvoryTower, A]): IO[A] =
    IO.io(rw => Free.return_(st(rw)))

  /**Put a value in a state thread */
  def returnST[S, A](a: => A): ST[S, A] =
    st(s => (s, a))

  /**Run a state thread */
  def runST[A](f: Forall[ST[?, A]]): A =
    f.apply.apply(ivoryTower)._2

  /**Allocates a fresh mutable reference. */
  def newVar[S]: Id ~> λ[α => ST[S, STRef[S, α]]] =
    new (Id ~> λ[α => ST[S, STRef[S, α]]]) {
      def apply[A](a: A) = returnST(stRef[S](a))
    }

  /**Allocates a fresh mutable array. */
  def newArr[S, A: ClassTag](size: Int, z: A): ST[S, STArray[S, A]] =
    returnST(stArray[S, A](size, z))

  /**Allows the result of a state transformer computation to be used lazily inside the computation. */
  def fixST[S, A](k: (=> A) => ST[S, A]): ST[S, A] = st(s => {
    lazy val ans: (Tower[S], A) = k(r)(s)
    lazy val (_, r) = ans
    ans
  })

  /**Accumulates an integer-associated list into an immutable array. */
  def accumArray[F[_], A : ClassTag, B](size: Int, f: (A, B) => A, z: A, ivs: F[(Int, B)])(implicit F: Foldable[F]): ImmutableArray[A] = {
    import std.anyVal.unitInstance
    type STA[S] = ST[S, ImmutableArray[A]]
    runST(new Forall[STA] {
      def apply[S] = for {
        a <- newArr(size, z)
        _ <- {
          F.foldMap(ivs)((x: (Int, B)) => a.update(f, x._1, x._2))(stMonoid[S, Unit])
        }
        frozen <- a.freeze
      } yield frozen
    })
  }
}

sealed abstract class STInstance0 {
  implicit def stSemigroup[S, A](implicit A: Semigroup[A]): Semigroup[ST[S, A]] =
      Semigroup.liftSemigroup[ST[S, ?], A](ST.stMonad[S], A)
}

sealed abstract class STInstances extends STInstance0 {
  implicit def stMonoid[S, A](implicit A: Monoid[A]): Monoid[ST[S, A]] =
    Monoid.liftMonoid[ST[S, ?], A](stMonad[S], A)

  implicit def stMonad[S]: Monad[ST[S, ?]] =
    new Monad[ST[S, ?]] {
      def point[A](a: => A): ST[S, A] = returnST(a)
      def bind[A, B](fa: ST[S, A])(f: A => ST[S, B]): ST[S, B] = fa flatMap f
    }
}

Other Scala examples (source code examples)

Here is a short list of links related to this Scala ST.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.