4 ms·
react is not an example for a library that is supposed to be or even possible to be used in a pure functional programming way.
by valenterry 3y ago
react is not an example for a library that is supposed to be or even possible to be used in a pure functional programming way.
- adamwk 3y agoRight, there's definitely functional-inspired bones (e.g., a view is a function of state); but every hook is a side effect, even the redux ones. And I don't think it would even be improved by being pure; Elm has much more boilerplate to do similar things.
- valenterry 3y agohaha, Adam from SM, is it you?
- WorldMaker 3y agoReact can still be viewed as functional programming if you assume Hooks operate in/on/with an unnamed/untyped monad. ("Pure" of course depends on your take of monadic programming from there.) It might be nice if that monad were better typed and/or at least parametric (reflected in input or output parameters), but it all exists in an untyped language to begin with, so it is mostly fine how it works right now. Mostly.
- valenterry 3y agoI don't know. I haven't used hooks much, but while you might consider it pure-functional in a way within a component that uses (a single) hook, I think using multiple hooks and having everything integrated is certainly not pure-functional. It's easy to test right? Can you replace calls/expressions with their result-value? If no, it's not pure-functional.
- WorldMaker 3y agoLike I said, I don't think it counts as "pure" functional because it is heavily monadic. Many Haskell users still think non-monadic code is "more pure" than say anything that uses the IO Monad and Hooks are "worse" than the IO Monad. (Especially some of the "Suspense" project Hooks which combine IO and Futures and State and more from a Haskell standpoint into one super weird monad.) You can certainly replace most hooks with static return values. Many hooks are heavily memoizable and in turn heavily memoized which is how they find their performance in practice. Multi-hook interactions generally follow a lot of the laws of monadic binding and a lot of the "hooks rules" aren't that strange in terms of monads: monadic binds have sequencing that matters (and dependencies you might track). The order of hooks matter in the same way that the order of IO binds or the order of Futures/Promises awaits. Again, it is certainly hard to call it "pure" functional in most ways, it has a lot of impurity, but it is certainly "deeply" functional. There's not really a better paradigm to call what is React is doing with Hooks than "functional programming". The language of monads is somewhat helpful in reasoning about how Hooks work and where they sit in the paradigm. They definitely make everything a bit more "impure", especially from the strict mathematical sense of "pure functions are entirely dependent on their parameters". Especially with Hooks not being represented parametrically (which I did mention I think can be something of a problem and I wish wasn't the case).
- valenterry 3y ago> You can certainly replace most hooks with static return values. "most" is not good enough. The idea of PFP is precisely that there is no exception, otherwise all guarantees are void. If I cannot rely on an expression to be referential transparent, then it means I have to look into to find out - and with that, the advantage of PFP goes through the window. > The order of hooks matter in the same way that the order of IO binds or the order of Futures/Promises awaits. The difference is that if you create an effect in a PFP style (like in Haskell), the effect itself doesn't do anything. You can now combine that effect with another effect in some way, e.g. by sequencing, which means first effect A and then afterwards effect B is executed. Yes. But what you get back is, again, an effect that doesn't do anything. So what you need to do is to build a datastructure of effects. Do you do that with hooks? I don't think so. With hooks, you call one, then call another, and yeah, the result depends on the order just like with an effect monad like IO. But the difference is that once the line of code that calls the hook is executed, something happens and the world has changed. This is not true when you can the line of code that builds the datastructure for the effect execution. You would have handle hooks like promises for this to work in a PFP way. But maybe I misunderstand and you can clarify it with a code example? Otherwise, I just think it's about terminology. I agree that there is a relation between the two things, but we shouldn't give it the same name, because it is still not the same concept.
- WorldMaker 3y agoHooks definitely build a complex data structure. They don't actually run immediately/imperatively. Even `useEffect(callback, undefined)` (no defined dependencies) which gives the illusion that it runs "immediately" on every render is still an illusion of sorts and there's a complex scheduler apparatus feeding on the data structures under the hood that useEffect builds. The data structures that Hooks build in React gets built in a strangely bound, somewhat liminal `this` space so it effectively "disappears" in JS. That's certainly not how I would have built it. You are right that I probably would have used something more like JS Promises, given the choice. But I didn't build React's Hook systems, I'm just an outside critic. I'm very happy to agree that use of `this` bound things is about as impure functionally as you get in JS. (That said, it is a very JS solution that predates React and gets to old debates of whether or not JS is truly "OO". Prototypical OO is a gray space between OO and functional paradigms.) Hooks are never imperative, even in the most complex multi-hook components. They use and build data structures. Those data structures are mostly hidden from view and hard to inspect, but they exist.
- nine_k 3y agoLook, you have a large stream of pure functions that exchange immutable data. There is a place where you can thread in the effects, and it's not entirely like using >>=, but after it, it's immutable data and pure functions again. It's very different from jQuery and the callback hell, or from any two-way bindings all the way to Visual Basic. It teaches you to value immutability and purity, to crave it (then comes Ramda, etc). Also, Promises are not entirely monadic, and `async` is not entirely the do-notation, but you can use a lot of monadic approaches, and reap some of the benefits.
- valenterry 3y ago> and it's not entirely like using >>= Exactly, and that's why it is not pf. It's really as simple as that. It's also not as if it would be theoretical distinction that has no meaning for praxis. It does. For instance, since I cannot control the execution of React's cycle (including rendering) it becomes hard(er) to do certain kind of page animations that should happen between renders. > It's very different from jQuery and the callback hell Yes, it is nicer to use. But it is not pfp-style.
- nine_k 3y agoWhat would you suggest as a pure enough example of FP GUI? Anything besides Elm, I mean? :)
- valenterry 3y agoI have never worked with one professionally (I rarely do frontend work anyways) and for my own projects I used react, dirty and productive as it is. ;)