|
Scala example source code file (ST.scala)
The ST.scala Scala example source codepackage 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 |
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.