Purity Reflection
Note: This feature is experimental and not yet intended for use.
Purity reflection is an advanced Flix feature that 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 =
typematch f {
case g: a -> Bool \ {} =>
if (useParallelEvaluation(s))
let h = (k, _) -> g(k);
let Set(t) = s;
RedBlackTree.parCount(threads() - 1, h, t) as \ {}
else
foldLeft((b, k) -> if (f(k)) b + 1 else b, 0, s)
case g: a -> Bool \ ef => foldLeft((b, k) -> if (g(k)) b + 1 else b, 0, s)
case _: _ => unreachable!()
}
Here the reifyEff
construct allows us to reflect on the purity of f
.
We have two cases: f
is guaranteed to be pure (in which case we bind it to g
and
take the first branch) and f
may be impure.
If f
is pure then we apply it in parallel over the set. Otherwise we apply it
sequentially.