Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Purity Reflection

Note: This is an advanced feature and should only be used by experts.

Purity reflection enables higher-order functions to inspect the purity of their function arguments.

This allows us to write functions that use selective lazy and/or parallel evaluation.

For example, here is the implementation of Set.count:

@ParallelWhenPure
pub def count(f: a -> Bool \ ef, s: Set[a]): Int32 \ ef =
    match purityOf(f) {
        case Purity.Pure(g) =>
            if (useParallelEvaluation(s))
                let h = (k, _) -> g(k);
                let Set(t) = s;
                RedBlackTree.parCount(h, t)
            else
                foldLeft((b, k) -> if (f(k)) b + 1 else b, 0, s)
        case Purity.Impure(g) => foldLeft((b, k) -> if (g(k)) b + 1 else b, 0, s)
    }

Here the purityOf function is used to reflect on the purity of f:

  • If f is pure then we evaluate Set.count in parallel over the elements of the set (if the set is big enough to warrant it).
  • If f is effectful then we use an ordinary (single-threaded) fold.

The advantage is that we get parallelism for free – if f is pure.