4 ms·
I was trying to write a comment making the same point but honestly, I'm not familiar enough with effects to know what exactly you can do with them. Good to know
by steinuil 5y ago
I was trying to write a comment making the same point but honestly, I'm not familiar enough with effects to know what exactly you can do with them. Good to know that I wasn't far off!
I'm curious about one thing though: unless you're passing a parameter that introduces an additional effect F into the function, what's the point of making it generic over the effect set? In a language with typed effects, all effects that could be performed by a function would already be known, so letting a unit function `fn get_user<F>() ->{F} T` where i.e. `F: DiagnosticData -> ()` decide which instance of an effect that takes a DiagnosticData and yields unit, as opposed to `fn get_user<F>(g: () ->{F} ()) ->{F} User` where the effect is clearly introduced by `g`, seems a bit overkill to me.
- isaacimagine 5y ago> unless you're passing a parameter that introduces an additional effect F into the function This definitely is overkill, I just wanted to illustrate that it was possible. You're correct: usually, a generic effect indicates you're passing a closure to the function that may execute additional effects: fn filter_users<F>( cond: fn<F>(User) ->{F} Bool, users: List<User> ) ->{F} List<User> If filter_users calls the closure cond, effect F will be performed, so filter_users must perform F as well. In the case where there are no external effects, F will be inferred to be the union of the empty set and whatever effects are used in the body of the function. Some languages are actually pretty strict about this, and explicitly declaring an empty effect set may mark the function as pure, which may not be what you want!