Function Arguments Are Not Function Colors

This article challenges the idea that function arguments, like Go's context.Context, are equivalent to function colors. It proposes a criterion: a color forces a change on all functions in the call stack, while a normal parameter change can be encapsulated. Using examples like context.Background() and Haskell's STM, it argues that async is not always a color, and that colors are about dependency shapes, not just syntax.

A color change escapes this encapsulation. All functions above it in the stack _must_ match its requirements.
  1. skavi

    Under this framework, Rust's async fns would not be colored, since any function in the callstack could be blocking on an executor. if you consider "spawn point" a part of the callstack, many other languages are similar.

    This doesn't feel like a useful distinction, but i don't think "function coloring" in general is a useful framework.

  2. legobmw99

    I think this is a fine distinction to make, though it's worth noting that function arguments _can be_ colors as the author describes if the arguments have to come from a specific place, e.g. in languages where only `main` receives certain arguments relating to system functionality, or a capability framework where only the top-level function receives the capability token.

  3. whateveracct

    Actually, the IO monad in haskell desugars to

    RealWorld -> (a, RealWorld)

    Where RealWorld is a "token" that is just meant to be threaded through. You cannot create one yourself, so you have to be given one.

    Thus, that function argument colors IO. Every PL feature is just an extension to System F.

  4. mitxela

    There's usually a way to run async on another thread (or this thread) and block on it, so async is not a color by your definition.

    I think color should be defined in terms of what you're likely going to do. You can call asyncio.run or context.Background or unsafePerformIO but they're both hacks that you shouldn't do because they are not correct, so we ignore them for colour analysis.

  5. smilekzs

    My personal yardsticks:

    How often does a conceptually incremental change correspond to a proportionally incremental code diff, vs. a surprisingly whole-world-upside-down rearchitect?

    Do the code patterns naturally leave enough room for you to incrementally shift/transpose how things are organized?

    When the answers to these are unfavorable, I often find what effects to "coloring" in the framework, library, or language, sometimes all at once.

More from this day

2026-09-08