Stream: ideas

Topic: function effectfulness without polymorphism


view this post on Zulip Sky Rose (Sep 02 2024 at 15:14):

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.

view this post on Zulip Richard Feldman (Sep 02 2024 at 15:28):

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:

view this post on Zulip Richard Feldman (Sep 02 2024 at 15:29):

Sky Rose said:

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.

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

view this post on Zulip Brendan Hansknecht (Sep 02 2024 at 16:52):

I feel like ! at the end of higher order effectful functions but not required for regular effectful functions would be quite strange.

view this post on Zulip Brendan Hansknecht (Sep 02 2024 at 16:53):

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

view this post on Zulip Brendan Hansknecht (Sep 02 2024 at 16:54):

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?

view this post on Zulip Brendan Hansknecht (Sep 02 2024 at 16:56):

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.

view this post on Zulip Richard Feldman (Sep 02 2024 at 16:56):

yeah exactly, that's the difference :thumbs_up:

view this post on Zulip Brendan Hansknecht (Sep 02 2024 at 17:00):

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.

view this post on Zulip Jasper Woudenberg (Sep 02 2024 at 18:34):

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