3 ms·
The same way you'd write "code that doesn't cause side effects" in Haskell. You cause side effects. The thing is with promises (like IO) the side effects are li
by inglor 11y ago
The same way you'd write "code that doesn't cause side effects" in Haskell. You cause side effects. The thing is with promises (like IO) the side effects are limited to a box you can open, process and close.
So given the same input the same function will always return the same output. If you have a function that asynchronously computes a random number - it won't return different numbers and will always return a promise for a random number. It will never be observable that being called with a different input it produced a different output (as long as you don't mutate global state or anything like that).
In Haskell, IO is implemented in a way that causes side effects at the platform level. If there are no side effects there is nothing going on and the program is a no op after all :) Monads like IO are about _limiting_ side effects and _controlling_ state.
In Haskell, the lack of side effects is by the fact IO is provided by the platform. There is no fundamental difference between Haskell's `getLine` and the DOM's `fetch`, both return a boxed value.
- dangoor 11y agoThanks for the followup! > In Haskell, the lack of side effects is by the fact IO is provided by the platform. There is no fundamental difference between Haskell's `getLine` and the DOM's `fetch`, both return a boxed value. In his talk about "effects"[1], Chris Armstrong also talked about making testing easier in Haskell, though I paid less attention to that part, to be honest. `fetch` returns a promise, but calling fetch causes the side effect to occur immediately. I don't know if that's how `getLine` works in Haskell. If I want to test code that calls `fetch` without an HTTP request actually hitting the network, I need to put in a mock `fetch`.[2] Or, if there was another return type that put the side effect in a box that the platform handles later (or not at all, in the case of a test), that seems like a win. [1]: https://www.youtube.com/watch?v=D37dc9EoFus https://www.youtube.com/watch?v=D37dc9EoFus [2]: another option, pointed out on Twitter, is that a promise (either from the fetch or from the test) could be passed in to the code under test. That seems less pleasant but requires no new machinery.
- inglor 11y agoFetch doesn't actually make an HTTP call - that's the thing :) Fetch boxes a value so that the _platform_ can make an HTTP call. You couldn't implement `fetch` yourself without platform APIs and you certainly couldn't do it in JavaScript without the DOM. The second suggestion you pointed (from Twitter) is exactly what you'd do in Haskell (you'd pass an IO from somewhere else). You can call it "pass an effect" if you'd like but it's the same thing :)
- dangoor 11y agoIndeed, the platform is responsible for the HTTP call, so I see what you mean. The side effect is happening in the platform itself. I should watch the second part of Chris Armstrong's video to see how he approached making testing nicer in Haskell.