Earlier quoted context omitted.
I like to explain functional programs like this. Functional programs don't _do_ anything, they are a list of commands some external interpreter (what you call the runtime, but doesn't have to be a runtime) will execute or compile. Functional programs only contain descriptions of the various commands, but it is an external interpreter executing the commands. Functional programs return "recipes". "recipes" are picked u…
This I can understand. But why would someone want to do this? It feels like mental overhead. So what advantages are there to a system like this?
How side effects work in FP
71–80 of 107 posts
Re: How side effects work in FP
#72> Equational Reasoning Probably the best reason to use FP imo. It just cuts out so much overhead when trying to read other people’s code.
A related advantage is expression-orientated code. In ML languages, code forms a beautiful tree structure where you can see the binding definition of each binding by looking down and right. let x = something really big and complicated whereas in a language built around statements it will be scattered all over: let x = null; x = something(); x = somethingElse(x); x = anotherThing(x); In the first case the definition o…
let x = anotherThing(
somethingElse(
something()
)
);Re: How side effects work in FP
#73FP explanations like this annoy me: That is, this code: x = foo() y = bar(x) z = bar(x) Should mean the same thing as: y = bar(foo()) z = bar(foo()) Because it's obvious to anyone that has written any sort of complex program that those are not the same thing. foo() can be an expensive operation like an HTTP call. Or it might depend on a database which can change state underneath it. I assume FP has answers for these…
Should mean the same thing as means has the same result value here. The operational semantics could be different, as you mention: even without side effects, computing x may be very expensive. This isn’t even special to FP, it’s a basic problem when building a compiler, namely whether inlining/common subexpression elimination is beneficial. To drive the point home, even in a language like Haskell these two examples mi…
Re: How side effects work in FP
#74Earlier quoted context omitted.
> Because it's obvious to anyone that has written any sort of complex program that those are not the same thing. They are the same thing in Haskell (except for when forcing the thunks into eager values happens, due to the weirdness of laziness, but that has nothing to do with purity). > I assume FP has answers for these things but the tutorials never cover them. Except this one does: > The
>They are the same thing in Haskell That just raises a different problem: y = bar(generateUUID()) z = bar(generateUUID()) >Except this one does: It doesn't explain it in the context of real world programming.
import System.Random
randomInt :: IO Int
randomInt = randomIO
isEven1 :: Int -> Bool
isEven1 n = (n `rem` 2) == 0
isEven2 :: IO Int -> IO Bool
isEven2 n = do
m
In example1, result1 and result2 may differ, which is signalled by the arrow (instead of "="). result2 and result2' cannot differ, which is signalled by "=", where the right hand side is verbatim the same.In example2, result1 and result2 may differ, which is signalled by "In example3, result1 and result3 may differ, which is signalled by "<-" (instead of "="). Another argument here is that they may differ, because example3 is the same as example2, except it used randomIntIsEven in place of isEven2 randomInt. But we defined randomIntIsEven to be equal to isEven2 randomInt, so result1 and result2 being able to be different in example2 but not in example3, or vice versa, would be a contradiction.
Re: How side effects work in FP
#75Earlier quoted context omitted.
>They are the same thing in Haskell That just raises a different problem: y = bar(generateUUID()) z = bar(generateUUID()) >Except this one does: It doesn't explain it in the context of real world programming.
> That just raises a different problem: y = bar(generateUUID()) z = bar(generateUUID()) You can't write that in Haskell! Instead you write something like. yuuid
Re: How side effects work in FP
#76Earlier quoted context omitted.
Actually the most important part of monads in Haskell is the do-notation. Without that, monadic code would look like JS' callback hell (although composition of monads using monad transformers/monad stacks isn't much better). Haskell without laziness is Purescript, btw.
I still think that it would look a lot less bad than JS callback hell, mostly because of syntax. actA >>= \a -> actB a >>= \b -> pure doSomethingWith b is a lot better (to my eyes) than: actA(a => actB(a, b => doSomethingWith(b) ) ) and it gets worse from there (blocks to have statements to declare variables, or to call multiple functions. pre ES6 those would've also been functions rather than lambdas. Admittedly mon…
Re: How side effects work in FP
#77"How to do side effects in s/FP/Haskell" Erlang is a functional programming language and doesn't need to jump through hoops to do side effects. So is OCaml. So is...
Somehow there is this school of thought that FP === Mirada/Haskell, go figure.
Re: How side effects work in FP
#78Earlier quoted context omitted.
Actually the most important part of monads in Haskell is the do-notation. Without that, monadic code would look like JS' callback hell (although composition of monads using monad transformers/monad stacks isn't much better). Haskell without laziness is Purescript, btw.
A lot of people I've talked to seem to think Purescript is a better Haskell.
- as of now it's tied mostly to the JS ecosystem and runtime(s): that means no TCO, which _really_ hurts when using monads that require on a lot of recursion. And in fact purescript sometimes has to take a performance penalty and use specific trampolined stack-safe monads to avoid stack overflows
- Haskell layout rules may be complex, but purescript's break in weird and unintuitive ways (by layout rules I mean the indentation-sensitive syntax)
- Haskell is catching up on _a lot_ of the feature that made/make purescript great (mostly talking about syntactic things right now, like RecordDotSyntax, QualifiedDo, BlockArguments...)
- as it turns out, when programming "Haskell-style", laziness is really damn effective. So many times I've had to forcefully (and painfully) introduce laziness in purescript to make things behave well...
As much as I like purescript, I think if you want that kind of strict programming, maybe OCaML or a derivative thereof (or maybe even ReasonML/Rescript?) would work better? I feel like whenever I use purescript it looks so similar to Haskell that I try doing things the haskell way and it just doesn't work, and the "purescript" way will often look weird to a trained haskeller.
Re: How side effects work in FP
#79Earlier quoted context omitted.
Actually the most important part of monads in Haskell is the do-notation. Without that, monadic code would look like JS' callback hell (although composition of monads using monad transformers/monad stacks isn't much better). Haskell without laziness is Purescript, btw.
A lot of people I've talked to seem to think Purescript is a better Haskell.
Re: How side effects work in FP
#80"How to do side effects in s/FP/Haskell" Erlang is a functional programming language and doesn't need to jump through hoops to do side effects. So is OCaml. So is...