liveBook · Manning

State token

As explained in Functional Programming in Scala, Second Edition

A state token is a value serving as type-level authorization to run computations that access or mutate a particular local state thread.

A state token is a value whose type authorizes access to one local state thread. The token does not represent the state; it only marks which computations may access or mutate it. section 14.2.2

The token works with ST, a local-effects monad whose underlying state transition cannot be invoked directly. Keeping the token type private to a computation prevents mutable state from escaping its intended scope. section 14.2.1

The authorization pattern has three important properties:

  • ST actions and the mutable references they create share the same S type. section 14.2.2
  • The S value itself is never inspected; possessing a value of type S merely permits an ST action to run. section 14.2.2
  • Opaque ST composition still supports map and flatMap while withholding direct access to the underlying function. section 14.2.1

Two cells, one authorization thread

An ST program allocates two mutable integer cells, reads them, swaps and increments their contents, then returns the pair. Choosing Nothing as S is syntactically possible, but the program cannot yet be run because ST remains opaque and no Nothing value can be supplied. section 14.2.2

Listing 14.2 Our new ST data type
opaque type ST[S, A] = S => (A, S)
object ST:
  extension [S, A](self: ST[S, A])
    def map[B](f: A => B): ST[S, B] =
      s =>
        val (a, s1) = self(s)
        (f(a), s1)
 
    def flatMap[B](f: A => ST[S, B]): ST[S, B] =
      s =>
        val (a, s1) = self(s)
        f(a)(s1)
 
  def apply[S, A](a: => A): ST[S, A] =
    lazy val memo = a                     #1
    s => (memo, s)
 
  def lift[S, A](f: S => (A, S)): ST[S, A] = f

Inspect the ST definition to see how an abstract S parameter threads through pure-looking map and flatMap operations. section 14.2.1

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Explains token authorization, shared type parameters, and opaque ST composition, but stops before showing how ST is finally run.
Examples
Uses STRef allocation, reads, writes, swapping, and incrementing across two mutable integer cells.
What it assumes
Assumes awareness of the State monad while emphasizing that ST deliberately hides direct access to its underlying function.
What you can do after
Build it from scratch by composing scoped ST actions and tagging mutable references with a shared authorization type.
How it connects
Connects state tokens to ST, the State monad, mutable references, type systems, and local effects.

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.