Hacker News new | ask | show | jobs
by G4BB3R 1890 days ago
People don't believe how typesafe Elm is until they start to use it, I never had a runtime exception. I worked a few years with TS+Vue/React, and now with Elm, and I will never go back. It is sad that a single FUD is shared much more than dozens of success stories.
2 comments

I had a runtime TYPE error not too long ago. Integers in elm are a lie. I got scientific notation for a float back when an integer went over the limit of javascript floats.

It was a stupid bug on my part that numbers got that big obviously but still. Take the no runtime errors with a grain of salt.

Did you try out https://package.elm-lang.org/packages/cmditch/elm-bigint/lat...? I've used that for things that I know exceed the browsers limits with JS numbers. Had to use it recently with something that returned a JS BigInt (which was a whole other buggy problem).
The problem with that is that by the time you have a problem it's too late.

Python has real integers that don't overflow. Elm does not.

What do you do when network requests fail for essential parts of the application?
The actions the code takes on error is up to you. What isn't up to you is whether or not you handle the error. Network calls give you a Result, and you have to deal with both the Ok and the Err branch or the code won't compile.
I'm not a language researcher/expert but real life code is full of colaterals and side effects, specially having to deal with things like network the expectation that f(x) will always resolve to a valid answer without resorting to result being of another sort even if normalized to the expected type (eg, you are doing a simple integer calculation and define that the negative numbers will be used as error codes to deal with side-effects).

I wonder whats the state-of-the-art approach from the FP community and if there's no really good answers, just patches like exceptions are, if in fact is the expectation and the classic assumptions of FP that are actually sort of broken?

I know i'm tripping here, but wonder if we managed to program in a "multidimensional-state paradigm", where you could call a "multidimensional f(x)" where in one dimension of the state it will always be a valid reply, and the side effects would be another f(x) that would solve the side-effects in parallel, but both functions would be intrinsically bounded to each other like in the schrodinger's cat experiment.

(Edit: to be clear here, is about the language itself to automate this, instead of expecting us to manually handling this or resorting to band-aids like exceptions which just forget about the state it was handling before. Its akin to state auto lifetime management as GC's, ref-counts, etc do, instead of expecting us to manually release the state as in a call to C's free())

You don't expect a function that hits the network to always return a valid answer though. That function would return a Result type which has Ok and Err constructors which you match against. Here's a self contained example that explains it better than I can[0].

> if we managed to program in a "multidimensional-state paradigm", where you could call a "multidimensional f(x)" where in one dimension of the state it will always be a valid reply, and the side effects would be another f(x) that would solve the side-effects in parallel, but both functions would be intrinsically bounded to each other like in the schrodinger's cat experiment.

You're _kind of_ talking about monadic binding here, which is called the `andThen` pattern in Elm. You can see it in JS when handling promises too.

[0] https://guide.elm-lang.org/effects/http.html

In most languages you can have more than one result or pack multiple values in a struct like object and that would simply solve this problem. Another way would be to return just the status code, knowing if it failed or succeeded and passing a closure to be called when the operations finish, either with 'ok' or 'failure' signal and the possible result.

Ok, we can do all of this now, but in this vision, you would have some sort of Ohad Rodeh btree, which would track all the states (it basically needs to be some sort of GC and handle all the state allocations).

With this btree you would be able to create branches of the whole universe of states in a memory cheap way. Once theres a possible state change a new branch is created, and once consolidated(not just one, but it might change many states of the tree) it would be passed as the "front state".

If a side-effect prevented the change in state from occurring nothing would happen as the original state would keep the same.

I know this sounds trouble and that we kind of have the tools for this, but i've noticed that we have a "fractured state" problem where we end up doing much more work that it would be not actually needed if we managed to pack it all in a ubiquitous initial signal that would get 'sliced' into other signals with transforms, but would be consolidated into one again.

Rendering got that right, with a back buffer with a bunch of intervening state that is flipped as front once its all set. If things are breaking in the back buffer, just try it again or fail the whole state tree all at once, keeping the last good state intact.

We already do this manually in code, but we manage a lot of fractured states giving we don't have the bird-eye view perspective.

If you had something managing it all, looking at diffs, etc, my intuition(maybe wrong) says that it would make a more efficient and stable program, more performant, with more memory efficiency and easier to reason about from the developer perspective.

> In most languages you can have more than one result or pack multiple values in a struct like object and that would simply solve this problem.

There are structs/records in like every FP language. The advantage of FP is that you can have the error code and description OR you can have the OK state value, but you can't have both in the same scope and the compiler guides you to that. And that rocks.

> you are doing a simple integer calculation and define that the negative numbers will be used as error codes to deal with side-effects

I had to come back to this because this kind of in-band signaling is how I've introduced bugs many-a-time in my old life. In FP it's so cheap to just make this function that can fail in some way return a wrapped up value that tells you what failed and how and _prevents_ you from doing math with what should be an error code (for instance).

You never leave the loading spinner state, but you don't throw. This actually inspired the Remote Data package which encourages you to break with the UI antipattern[0] where "result not yet loaded" is conflated with "we know there is nothing there." This pattern of handling those states has made its way into the official guide too, in case you want to start without using anything outside of the core library (a common pattern for new learners)[1]

[0] http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipatt... [1] https://guide.elm-lang.org/effects/http.html

Runtime exceptions aren't the same as bugs or sub optimal experiences. If the call for your data for your table fails and it shouldn't, your table will be sitting there awkwardly empty. But what won't happen is what's happened in lots of my Javascript projects historically which is a total whiteout of the screen and then when you open up console it has an error: "can't read property 'results' of null" or whatever.