One idea that hasn't been discussed in the marathon #ideas > function effectfulness syntax thread: Would it be possible to get away without being able to write functions that are polymorphic in their effectfulness.
TL;DR: there's no polymorphic functions or syntax, which means we're back to requiring two versions of some functions, but it removes a confusing concept from the language.
summary of discussion so far
The current leading idea (I think? I didn't follow everything.) is having 3 variants of functions:
alwaysPure: a, (a -> b) -> b
alwaysEffectful: a, (a => b) => b
polymorphic: a, (a -fx-> b) -fx-> b
The polymorphic version is verbose to type but that's okay because the hypothesis is that few functions would use it. Just parallel and walk. The default would be that most people write pure functions.
There was also a lot of discussion of writing the polymorphic version without the variable, and having no way to write an always pure function, but there was pushback because it makes it harder to tell whether code is effectful, and every higher-ordered function has to write defensively in case they're passed an effectful function.
new idea
What if polymorphic functions didn't exist. You can write higher-ordered functions that are always pure, or always assume their arguments are effectful.
You can still pass a pure function to an higher-order effectful function, but at that point is has to be treated like an effectful function even though it's not (like painting a blue function red), and also you probably don't have a reason to do that. You can't pass effectful functions to pure functions at all.
The main tradeoff is that there has to be pure and impure versions of some functions (like List.walk and List.walkEffects. If you really do want pure and impure versions this is way worse than the variable in the type signature. However, the hypothesis (so far unproven) is that very few of these would exist.
The benefit is that the concept of effect polymorphism is completely removed from the language. No syntax, no "-> means pure unless there's another -> in the signature". It's just -> means pure and => means impure.
Sky Rose said:
The benefit is that the concept of effect polymorphism is completely removed from the language. No syntax, no "
->means pure unless there's another->in the signature". It's just->means pure and=>means impure.
this would be a pretty nice benefit for the first release of such a big change, since we could always add effect polymorphism in a future release :thinking:
Sky Rose said:
The main tradeoff is that there has to be pure and impure versions of some functions (like
List.walkandList.walkEffects. If you really do want pure and impure versions this is way worse than the variable in the type signature. However, the hypothesis (so far unproven) is that very few of these would exist.
worth noting that Jasper's idea of making ! be part of the name of effectful functions would work nicely with this; you could have one function named List.walk and the other named List.walk! and it would be immediately obvious what the difference was
I feel like ! at the end of higher order effectful functions but not required for regular effectful functions would be quite strange.
Also, I feel like this is more or less the same as my only allow one effect variable solution. It is just a tiny bit more restricted
That solution was not preferred cause it meant building a record of higher order effectful and pure functions would promote everything to effectful. This would do the same?
Actually I guess this would just ban that maybe effectful record in the first place. The user would have to pick effectful or pure for each individual function in the record at compile time.
yeah exactly, that's the difference :thumbs_up:
Yeah, this idea sounds fine. Though I think we should use {} -> Type! in the type system if we are using ! in function names or for calling effectful functions.
I don't think we should allow naming higher order effectful functions with ! if effectful functions don't need ! to be called. I think that would just be a weird inconsistency and lead to more confusing code.
My thought was that if effectful function names must include !, that would remove the need to have extra notation for effects in the type signature, given that the function name is already part of the type signature.
Last updated: Jun 16 2026 at 16:19 UTC