<p>I've heard people say &quot;colored&quot; functions (e.g. <code>async</code> functions, or functions marked with <code>throws</code>) are bad because they pollute your code base, as every direct or indirect caller of a colored function becomes colored as well. Examples of languages which don't have colored functions are Go and Elixir.</p>
<p>However, is it wrong to think of these languages without colored functions as simply marking all functions as colored? For example, how is Go fundamentally different from C# with every function marked <code>async</code>?</p>

<functions>
Colored vs uncolored functions
CC BY-SA 4.0
2023-12-26T12:52:18.563Z
I don't think it is particularly sensible to call these functions "coloured" and "uncoloured". When using colours as a metaphor, one usually assigns a single colour to every entity, so in this case you would only have two colours ‒ pure-coloured and effect-coloured. In [my article](https://is4code.blogspot.com/2020/01/what-flavour-is-your-function.html) I call them flavours, and define them a bit more rigorously.
IS4
CC BY-SA 4.0
2024-01-02T20:16:47.643Z
When *every* function is colored, *none* of them are.
dan04
<p>One way to interpret &quot;color&quot; is just another term for effect [1]. An <strong>effect</strong> is a specific attribute a function may have which propagates to its callers. Async and <code>throws</code> are effects, but so are &quot;does IO&quot;, non-determinism, and even potential non-termination (if a function has the potential to infinitely recurse, it can't be used to prove things via the <a href="https://en.wikipedia.org/wiki/Curry%E2%80%93Howard_correspondence" rel="noreferrer">Curry–Howard correspondence</a>). A function which calls an async function must be async and a function which calls a <code>throws</code> function must be <code>throws</code>, similarly a function which calls an IO-capable function is itself IO-capable, etc. [2].</p>
<p>I'd argue that <strong><em>every</em> language has functions with multiple colors</strong>. It's just that in some languages like C and JavaScript the colors are implicit, in some languages like Haskell the colors are explicit in the function signature (monads like <code>IO</code>, <code>Future</code>, <code>State</code>), and some languages like C++ and Java some colors (<code>async</code>, <code>const</code> member function, <code>throws</code>) are explicit and the rest are implicit. Even in Go which don't have <code>async</code>, some functions are entirely single-threaded and others spawn goroutines, you just can't tell by the signature; similarly in JavaScript some functions will never throw exceptions and others may, and in Java some methods won't mutate <code>this</code> and others will, but you can't tell by the function signatures. *Go is fundamentally different from C# in that both support asynchronous functions, but Go's functions are defined and called no differently than synchronous ones, while C#'s asynchronous functions must be prefixed <code>async</code> and called with <code>await</code> (or explicitly handled with something like <code>.GetAwaiter().GetResult()</code>).</p>
<p>You can argue that <strong>the syntax of languages without explicit colors/effects is less polluted</strong>. In Go, you don't have to denote all of your async functions with extra syntax, and in JavaScript, you don't have to put <code>throws IOException</code> after every function which invokes IO (or spam <code>try { ... } catch (e) { throw new RuntimeException(e); }</code>). In fact, this is probably a big reason why languages where every effect must be explicit haven't caught on, because it would be a big pain to write signatures like <code>async nondeterministic nonterminating ioperforming FooBar(arg: int, arg2: string) throws IOException, TimeoutException, BazException</code> (and there are plenty of reasonable, small functions which would have many types of effects).</p>
<p>However, languages &quot;without&quot; colored functions (without explicit effects) are no less &quot;polluted&quot; than those with them, because every language has colored functions, those languages are just hiding the pollution :). In fact, <strong>languages without explicit syntax usually have more effects</strong>, because programmers can't hide unreasonable side-effects from their API, and class signatures may disallow unreasonable effects. For example, <a href="https://news.ycombinator.com/item?id=21765788" rel="noreferrer">Java's <code>URL.equals</code> performs DNS resolution, and the result can be different depending on whether or not you are connected to the internet or if a server's IP address changed</a>. If Java was forced to denote that <code>Object.equals</code> could potentially access the internet, more people may be dissuaded from using Java; or more likely, the developers of Java may have figured out a more reasonable solution (like, not using DNS resolution to compare URLs).</p>
<hr />
<p>[1] <a href="https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/" rel="noreferrer">&quot;What color is your function&quot;</a>, which I believe is the origin of &quot;color&quot;, defines colors a different way: pure functions are blue, functions which perform an effect are red. Here, pure functions are colorless or grayscale, and different effects correspond to different colors.</p>
<p>The terminology &quot;color&quot; is used because it helps to show effects by highlighting functions with each effect in their specific color, like the article does. If you have multiple effects, each may correspond to a different color (green, orange, blue), then a function with multiple effects would have to have multiple colors.</p>
<p>[2] Unless the function uses an <strong>effect handler</strong>, which effectively consumes the effect so it's no longer observable to the outside world. Ex: calling an <code>async</code> function with <code>.GetAwaiter().GetResult()</code> to simply block until it returns, calling a <code>throws</code> function within a <code>try</code> block to catch the exception, calling an IO-capable function on a virtual filesystem, calling a non-deterministic function with a seeded random, or calling a potentially non-terminating function but only running a finite number of steps and then &quot;giving up&quot; if it doesn't terminate.</p>

CC BY-SA 4.0
2023-12-24T00:27:08.917Z
2023-12-26T13:52:20.850Z
2023-12-26T13:52:20.850Z
tarzh
CC BY-SA 4.0
2023-12-24T04:08:50.967Z
How would one use "color" to describe a function which receives a callback, and will never thorw if the callback never throws, but will propagate any exceptions thrown by the callback?
supercat
CC BY-SA 4.0
2023-12-24T10:53:52.830Z
@supercat It's generic over the color of its callback parameter?
Bergi
CC BY-SA 4.0
2023-12-24T20:51:45.343Z
How about "effect polymorphic" systems with "effect inference"? It seems like that could simplify things like your example quite a bit. But they would still allow you to restrict things when you want to. I'm sure there are tradeoffs with that, but maybe it would be interesting. Monad transformers are sort of like this, but I know there are other approaches as well.
David Young
CC BY-SA 4.0
2023-12-24T21:05:11.477Z
You can be more precise about your claim that all languages have colors. Specifically, any language with higher-order functions can encode the [continuation monad](https://ncatlab.org/nlab/show/continuation+monad), which is the [mother of all monads](http://blog.sigfpe.com/2008/12/mother-of-all-monads.html).
Corbin
CC BY-SA 4.0
2023-12-25T04:02:12.877Z
@supercat I'd say that function is "transparent".
InSync
CC BY-SA 4.0
2023-12-26T13:48:06.293Z
If you don’t mark your callbacks red, do colorless/blue ideas sleep furiously?
Davislor
CC BY-SA 4.0
2023-12-31T21:01:02.377Z
Beware; `.GetAwaiter().GetResult()` doesn't fully uncolor a function. If you have an `async` call higher up on the callstack, this is deadlocky. Most of the documentation says its a soft deadlock, but if you have less than 1MB of RAM one second later, you will deadlock forever. Note that this is the right way to call an `async` function from a thread from `new Tread()` or from (non-`async`) `Main()`.
Joshua
<p>I think that &quot;colored functions are bad&quot; is the wrong conclusion to come away from that article with. As mentioned by the other answers, the original source of the &quot;color&quot; analogy for functions is <a href="https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/" rel="noreferrer">https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/</a>.</p>
<p>For those who haven't read it, I'll summarize here. Imagine a hypothetical programming language where every function must be marked (at declaration time) with a color. Every function is either red or blue. And red and blue functions are intentionally designed asymmetrically. Red functions can do whatever they please, but blue functions are locked in and can, generally speaking, only call other blue functions. In principle, you should always make your functions blue, because then blue <em>and</em> red callers can use it, but the standard library of our clever little nonexistent language has marked some of its functions as red. So if you need to use <em>those</em> functions, you're stuck in the red as well.</p>
<p>The author of the article was using &quot;red&quot; as a stand-in for <code>async</code> in Javascript and &quot;blue&quot; for non-<code>async</code>, but it turns out that the analogy works in several places.</p>
<ul>
<li>Javascript and Python both define <code>async</code> functions (red) and non-<code>async</code> ones (blue).</li>
<li>Haskell requires you to distinguish between <code>IO</code>-bound functions (red) and those that are pure (blue).</li>
<li>Rust forces you to mark <code>unsafe</code> functions (red) and assumes all others are safe (blue).</li>
<li>Java requires checked exceptions to be marked in the return type (red), and assumes all functions which do not have a <code>throws</code> clause do not throw checked exceptions (blue).</li>
</ul>
<p>In each of these cases, there are escape hatches of varying utility.</p>
<ul>
<li>A non-<code>async</code> function in Javascript can start up a web worker or some other asynchronous technique that doesn't block the current worker.</li>
<li>Haskell has <code>unsafePerformIO</code>, an extremely blunt force instrument that can be used <em>very</em> carefully to perform <code>IO</code> effects in otherwise pure contexts.</li>
<li>Rust allows blocks of code within a function to be marked as <code>unsafe</code>, allowing a blue function to masquerade as red for a moment without actually becoming red.</li>
<li>Java lets you wrap checked exceptions in an unchecked one like <code>RuntimeException</code>, which can slip right through the <code>throws</code> declaration.</li>
</ul>
<p>The point of the red-blue analogy isn't &quot;Colored functions are bad and we should avoid them&quot;. The point is &quot;We should be conscious of the distinctions we define in our languages&quot;. If Java didn't have <code>RuntimeException</code>, people would hate checked exceptions <em>even more</em> than they already do. If Rust didn't let you assert your dominance to the compiler with <code>unsafe { ... }</code> blocks, then lots of basic functions (such as those on a benign data structure like <code>Vec</code>) would have to be red on principle.</p>
<p>If you omit the colored distinction, all your functions are blue. If you let things get out of hand, then all your functions are red. And you certainly don't want to end up in a situation where all of your users are marking their functions red simply because it's too much of a pain to prove blue-ness. If they start doing that, then all you have is a colorless language with a couple of annoying keywords that do nothing.</p>
<p>But <em>when done correctly</em>, and when done sparingly, we can get tangible benefits.</p>
<ul>
<li>Stackless coroutines with explicit <code>async</code> give us some nice performance benefits over Lua-style or Go-style stackful coroutines (see <a href="https://langdev.stackexchange.com/questions/697/what-are-the-benefits-of-stackful-vs-stackless-coroutines">this related question</a> for more discussion on that topic)</li>
<li>Explicit marking of impure effects in Haskell allows us to reason about our code in a way that many other languages can't do.</li>
<li>Rust's safety guarantees (which apply to any part of the code <em>not</em> marked <code>unsafe</code>) prevent a lot of bugs, and often isolate those that occur to the (hopefully small) red part of your program.</li>
<li>While people hate on Java's checked exceptions, the <em>principle</em> that exceptional code should be marked and ignoring it should be a compiler error is actually a really good one. We see a more refined approach to this in Rust (<code>Result</code> types) and Haskell (error monads).</li>
</ul>
<p>So the color problem isn't really a <em>problem</em>, in the same way that the law of gravity isn't a problem for an airline pilot. It's something we should be aware of, and something that can provide us some real tangible benefits when applied correctly. But it's not an evil to be smited.</p>

CC BY-SA 4.0
2023-12-24T06:35:04.790Z
2023-12-24T06:35:04.790Z
Silvio Mayolo
CC BY-SA 4.0
2023-12-24T07:15:31.213Z
Doesn't `IO` being represented as an actual, first-class type instead of keyword not also mean that Haskel can "automatically color" other functions for you if they are generic? Speaking from my experience doing a lot of `async` Python, the main problem there is that higher-order functions cannot be generic w.r.t. `async`, meaning one needs two sets of `map`, `filter`, …. This always feels like something that would be easily solvable with mechanisms akin to generics and templates, which Python sadly doesn't have in that way.
MisterMiyagi
CC BY-SA 4.0
2023-12-24T08:02:03.617Z
'Stackless coroutines with explicit async give us some nice performance benefits over Lua-style or Go-style stackful coroutines' no, it gives you some performance _tradeoffs_, which some (myself included) would argue land you in a generally worse place.
Moonchild
CC BY-SA 4.0
2023-12-24T15:59:40.603Z
@MisterMiyagi Yeah, that's fair. One of the really nice things about Haskell's effect system is that it's first-class, so you *can* write a function like `Monad m => (a -> m b) -> ([a] -> m [b])` and get a higher-order effect. I still consider that colored, it's just that Haskell is advanced enough to let you parameterized by "color". Scala has begun experimenting with higher-order effects in its capabilities (basically, they reintroduced checked exceptions using `implicit` contextual abstractions). So yes, higher-order effects are a really cool solution, though hard to make intuitive.
Silvio Mayolo
CC BY-SA 4.0
2023-12-24T16:00:47.273Z
@Moonchild I'd love to hear your thoughts on that, actually. I don't know a ton about coroutine implementations and was just going off of what was said on the linked question. If you have a lot to say on the topic, I'd encourage you to post an answer to the question I linked in the post.
Silvio Mayolo
CC BY-SA 4.0
2023-12-24T18:34:02.960Z
The `unsafe` block in Rust does not allow unsafe functions to masquerade as safe. It's just the intended way to call unsafe functions. It's perfectly safe as long as the preconditions are respected.
mousetail 'he-him'
CC BY-SA 4.0
2023-12-25T05:38:30.370Z
@mousetail The "masquerade" description is precisely the other way around: it lets blue (safe) functions behave like red (unsafe) functions for the purpose of being allowed to call red functions.
Unrelated String
CC BY-SA 4.0
2023-12-25T12:12:03.727Z
@UnrelatedString I still think that is inaccurate, an unsafe function just has some preconditions that can't be checked by the compiler. It's not masquerading to use an unsafe block to indicate you have manually checked the preconditions
mousetail 'he-him'
<p>When we say a language has coloured functions, it means that <strong><em>every</em> function is coloured</strong>; the thing that was worth noting was that there can be <em>different</em> colours on different functions, and the different colours are incompatible somehow.  It's about segmentation of the call graph, rather than anything particularly intrinsic to the functions being coloured themselves.</p>
<p>A system with every function having the same colour is reductively still coloured, but with no follow-on implications, and that's the same thing as giving them the colour &quot;no colour&quot;. It makes no difference whether that single colour is marking everything async (throws, impure, ...) or not. You can freely think of that language as marking all functions as coloured octarine, or as not colouring any functions, as you wish.</p>
<p>Now, Go <em>is</em> fundamentally different than C# with every function marked <code>async</code>, but that's not to do with the function colouring but with how their particular models work, and I don't think that's what you're asking about.</p>

CC BY-SA 4.0
2023-12-23T20:20:09.707Z
2023-12-23T20:20:09.707Z
Michael Homer
# Colored vs uncolored functions
Posted by: username_0 on 2023-12-23
I've heard people say "colored" functions (e.g. `async` functions, or functions marked with `throws`) are bad because they pollute your code base, as every direct or indirect caller of a colored function becomes colored as well. Examples of languages which don't have colored functions are Go and Elixir.

However, is it wrong to think of these languages without colored functions as simply marking all functions as colored? For example, how is Go fundamentally different from C# with every function marked `async`?
**Tags:** functions
> **Comments:**
> **username_1**: I don't think it is particularly sensible to call these functions "coloured" and "uncoloured". When using colours as a metaphor, one usually assigns a single colour to every entity, so in this case you would only have two colours ‒ pure-coloured and effect-coloured. In [my article](https://is4code.blogspot.com/2020/01/what-flavour-is-your-function.html) I call them flavours, and define them a bit more rigorously.  
> **username_2**: When *every* function is colored, *none* of them are.  
---
## 3 answers
### Answer by username_3 on 2023-12-24. Score: 34 | Accepted answer
One way to interpret "color" is just another term for effect [1]. An **effect** is a specific attribute a function may have which propagates to its callers. Async and `throws` are effects, but so are "does IO", non-determinism, and even potential non-termination (if a function has the potential to infinitely recurse, it can't be used to prove things via the [Curry–Howard correspondence](https://en.wikipedia.org/wiki/Curry%E2%80%93Howard_correspondence)). A function which calls an async function must be async and a function which calls a `throws` function must be `throws`, similarly a function which calls an IO-capable function is itself IO-capable, etc. [2].

I'd argue that ***every* language has functions with multiple colors**. It's just that in some languages like C and JavaScript the colors are implicit, in some languages like Haskell the colors are explicit in the function signature (monads like `IO`, `Future`, `State`), and some languages like C++ and Java some colors (`async`, `const` member function, `throws`) are explicit and the rest are implicit. Even in Go which don't have `async`, some functions are entirely single-threaded and others spawn goroutines, you just can't tell by the signature; similarly in JavaScript some functions will never throw exceptions and others may, and in Java some methods won't mutate `this` and others will, but you can't tell by the function signatures. \*Go is fundamentally different from C# in that both support asynchronous functions, but Go's functions are defined and called no differently than synchronous ones, while C#'s asynchronous functions must be prefixed `async` and called with `await` (or explicitly handled with something like `.GetAwaiter().GetResult()`).

You can argue that **the syntax of languages without explicit colors/effects is less polluted**. In Go, you don't have to denote all of your async functions with extra syntax, and in JavaScript, you don't have to put `throws IOException` after every function which invokes IO (or spam `try { ... } catch (e) { throw new RuntimeException(e); }`). In fact, this is probably a big reason why languages where every effect must be explicit haven't caught on, because it would be a big pain to write signatures like `async nondeterministic nonterminating ioperforming FooBar(arg: int, arg2: string) throws IOException, TimeoutException, BazException` (and there are plenty of reasonable, small functions which would have many types of effects).

However, languages "without" colored functions (without explicit effects) are no less "polluted" than those with them, because every language has colored functions, those languages are just hiding the pollution :). In fact, **languages without explicit syntax usually have more effects**, because programmers can't hide unreasonable side-effects from their API, and class signatures may disallow unreasonable effects. For example, [Java's `URL.equals` performs DNS resolution, and the result can be different depending on whether or not you are connected to the internet or if a server's IP address changed](https://news.ycombinator.com/item?id=21765788). If Java was forced to denote that `Object.equals` could potentially access the internet, more people may be dissuaded from using Java; or more likely, the developers of Java may have figured out a more reasonable solution (like, not using DNS resolution to compare URLs).

---

[1] ["What color is your function"](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/), which I believe is the origin of "color", defines colors a different way: pure functions are blue, functions which perform an effect are red. Here, pure functions are colorless or grayscale, and different effects correspond to different colors.

The terminology "color" is used because it helps to show effects by highlighting functions with each effect in their specific color, like the article does. If you have multiple effects, each may correspond to a different color (green, orange, blue), then a function with multiple effects would have to have multiple colors.

[2] Unless the function uses an **effect handler**, which effectively consumes the effect so it's no longer observable to the outside world. Ex: calling an `async` function with `.GetAwaiter().GetResult()` to simply block until it returns, calling a `throws` function within a `try` block to catch the exception, calling an IO-capable function on a virtual filesystem, calling a non-deterministic function with a seeded random, or calling a potentially non-terminating function but only running a finite number of steps and then "giving up" if it doesn't terminate.
> **Comments:**
> **username_4** (2023-12-24): How would one use "color" to describe a function which receives a callback, and will never thorw if the callback never throws, but will propagate any exceptions thrown by the callback?  
> **username_5** (2023-12-24): @supercat It's generic over the color of its callback parameter?  
> **username_6** (2023-12-24): How about "effect polymorphic" systems with "effect inference"? It seems like that could simplify things like your example quite a bit. But they would still allow you to restrict things when you want to. I'm sure there are tradeoffs with that, but maybe it would be interesting. Monad transformers are sort of like this, but I know there are other approaches as well.  
> **username_7** (2023-12-24): You can be more precise about your claim that all languages have colors. Specifically, any language with higher-order functions can encode the [continuation monad](https://ncatlab.org/nlab/show/continuation+monad), which is the [mother of all monads](http://blog.sigfpe.com/2008/12/mother-of-all-monads.html).  
> **username_8** (2023-12-25): @supercat I'd say that function is "transparent".  
> **username_9** (2023-12-26): If you don’t mark your callbacks red, do colorless/blue ideas sleep furiously?  
> **username_10** (2023-12-31): Beware; `.GetAwaiter().GetResult()` doesn't fully uncolor a function. If you have an `async` call higher up on the callstack, this is deadlocky. Most of the documentation says its a soft deadlock, but if you have less than 1MB of RAM one second later, you will deadlock forever. Note that this is the right way to call an `async` function from a thread from `new Tread()` or from (non-`async`) `Main()`.  
---
### Answer by username_11 on 2023-12-24. Score: 11
I think that "colored functions are bad" is the wrong conclusion to come away from that article with. As mentioned by the other answers, the original source of the "color" analogy for functions is <https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/>.

For those who haven't read it, I'll summarize here. Imagine a hypothetical programming language where every function must be marked (at declaration time) with a color. Every function is either red or blue. And red and blue functions are intentionally designed asymmetrically. Red functions can do whatever they please, but blue functions are locked in and can, generally speaking, only call other blue functions. In principle, you should always make your functions blue, because then blue *and* red callers can use it, but the standard library of our clever little nonexistent language has marked some of its functions as red. So if you need to use *those* functions, you're stuck in the red as well.

The author of the article was using "red" as a stand-in for `async` in Javascript and "blue" for non-`async`, but it turns out that the analogy works in several places.

* Javascript and Python both define `async` functions (red) and non-`async` ones (blue).
* Haskell requires you to distinguish between `IO`-bound functions (red) and those that are pure (blue).
* Rust forces you to mark `unsafe` functions (red) and assumes all others are safe (blue).
* Java requires checked exceptions to be marked in the return type (red), and assumes all functions which do not have a `throws` clause do not throw checked exceptions (blue).

In each of these cases, there are escape hatches of varying utility.

* A non-`async` function in Javascript can start up a web worker or some other asynchronous technique that doesn't block the current worker.
* Haskell has `unsafePerformIO`, an extremely blunt force instrument that can be used *very* carefully to perform `IO` effects in otherwise pure contexts.
* Rust allows blocks of code within a function to be marked as `unsafe`, allowing a blue function to masquerade as red for a moment without actually becoming red.
* Java lets you wrap checked exceptions in an unchecked one like `RuntimeException`, which can slip right through the `throws` declaration.

The point of the red-blue analogy isn't "Colored functions are bad and we should avoid them". The point is "We should be conscious of the distinctions we define in our languages". If Java didn't have `RuntimeException`, people would hate checked exceptions *even more* than they already do. If Rust didn't let you assert your dominance to the compiler with `unsafe { ... }` blocks, then lots of basic functions (such as those on a benign data structure like `Vec`) would have to be red on principle.

If you omit the colored distinction, all your functions are blue. If you let things get out of hand, then all your functions are red. And you certainly don't want to end up in a situation where all of your users are marking their functions red simply because it's too much of a pain to prove blue-ness. If they start doing that, then all you have is a colorless language with a couple of annoying keywords that do nothing.

But *when done correctly*, and when done sparingly, we can get tangible benefits.

* Stackless coroutines with explicit `async` give us some nice performance benefits over Lua-style or Go-style stackful coroutines (see [this related question](https://langdev.stackexchange.com/questions/697/what-are-the-benefits-of-stackful-vs-stackless-coroutines) for more discussion on that topic)
* Explicit marking of impure effects in Haskell allows us to reason about our code in a way that many other languages can't do.
* Rust's safety guarantees (which apply to any part of the code *not* marked `unsafe`) prevent a lot of bugs, and often isolate those that occur to the (hopefully small) red part of your program.
* While people hate on Java's checked exceptions, the *principle* that exceptional code should be marked and ignoring it should be a compiler error is actually a really good one. We see a more refined approach to this in Rust (`Result` types) and Haskell (error monads).

So the color problem isn't really a *problem*, in the same way that the law of gravity isn't a problem for an airline pilot. It's something we should be aware of, and something that can provide us some real tangible benefits when applied correctly. But it's not an evil to be smited.
> **Comments:**
> **username_12** (2023-12-24): Doesn't `IO` being represented as an actual, first-class type instead of keyword not also mean that Haskel can "automatically color" other functions for you if they are generic? Speaking from my experience doing a lot of `async` Python, the main problem there is that higher-order functions cannot be generic w.r.t. `async`, meaning one needs two sets of `map`, `filter`, …. This always feels like something that would be easily solvable with mechanisms akin to generics and templates, which Python sadly doesn't have in that way.  
> **username_13** (2023-12-24): 'Stackless coroutines with explicit async give us some nice performance benefits over Lua-style or Go-style stackful coroutines' no, it gives you some performance _tradeoffs_, which some (myself included) would argue land you in a generally worse place.  
> **username_11** (2023-12-24): @MisterMiyagi Yeah, that's fair. One of the really nice things about Haskell's effect system is that it's first-class, so you *can* write a function like `Monad m => (a -> m b) -> ([a] -> m [b])` and get a higher-order effect. I still consider that colored, it's just that Haskell is advanced enough to let you parameterized by "color". Scala has begun experimenting with higher-order effects in its capabilities (basically, they reintroduced checked exceptions using `implicit` contextual abstractions). So yes, higher-order effects are a really cool solution, though hard to make intuitive.  
> **username_11** (2023-12-24): @Moonchild I'd love to hear your thoughts on that, actually. I don't know a ton about coroutine implementations and was just going off of what was said on the linked question. If you have a lot to say on the topic, I'd encourage you to post an answer to the question I linked in the post.  
> **username_14** (2023-12-24): The `unsafe` block in Rust does not allow unsafe functions to masquerade as safe. It's just the intended way to call unsafe functions. It's perfectly safe as long as the preconditions are respected.  
> **username_15** (2023-12-25): @mousetail The "masquerade" description is precisely the other way around: it lets blue (safe) functions behave like red (unsafe) functions for the purpose of being allowed to call red functions.  
> **username_14** (2023-12-25): @UnrelatedString I still think that is inaccurate, an unsafe function just has some preconditions that can't be checked by the compiler. It's not masquerading to use an unsafe block to indicate you have manually checked the preconditions  
---
### Answer by username_16 on 2023-12-23. Score: 11
When we say a language has coloured functions, it means that ***every* function is coloured**; the thing that was worth noting was that there can be *different* colours on different functions, and the different colours are incompatible somehow. It's about segmentation of the call graph, rather than anything particularly intrinsic to the functions being coloured themselves.

A system with every function having the same colour is reductively still coloured, but with no follow-on implications, and that's the same thing as giving them the colour "no colour". It makes no difference whether that single colour is marking everything async (throws, impure, ...) or not. You can freely think of that language as marking all functions as coloured octarine, or as not colouring any functions, as you wish.

Now, Go *is* fundamentally different than C# with every function marked `async`, but that's not to do with the function colouring but with how their particular models work, and I don't think that's what you're asking about.
---
