HNHacker News
TopNewBestAskShowJobs

jfmengels1

85 karma · joined January 28, 2021

submissionscomments
jfmengels1··on Road to Elm 1.0
Custom kernel never was a feature the language had. It was an implementation detail that people discovered they could hack, but it was never meant as a feature.
jfmengels1··on Tail recursion, but modulo cons
Oh ok. I didn't mean to "reject" the solution, since that's what I see done most of the time in practice, because of the current limitations of the language regarding stack safety.

For foldr, I mean that specific implementation - which fully prioritizes performance and uses several levels of unwrapping, etc. - is hard to reuse for functions we wish to maintain. Using List.foldr is fine (when applicable, which is not always), but copy-pasting its implementation to adapt it to our need isn't, from a maintenance point of view.

On the topic of continuation-passing style, I don't personally believe that the solution I've highlighted uses CPS. At least from my shallow understanding, CPS uses functions, which my solution doesn't. CPS can easily emulate TRMC, but TRMC works differently (and is more performant though is applicable to less situations).

My understanding of CPS is maybe shallow, so I could be missing some understanding, but to me they're different and therefore not part of my explanation.

> Continuations provide the structure to hold your "holes" until they can be filled in

That's one mental model to view it, but there isn't actually any "real" hole to fill with CPS, whereas with TRMC there is (at least for data construction).

jfmengels1··on Tail recursion, but modulo cons
The mapHelper version that was rejected changed the order. The one that did `List.reverse` had the correct order, and this one is equivalent to the List.foldr solution.

The only difference is List.foldr's implementation is more performant (up to a certain number of elements as you say). If this is not what you asked, then I did not understand the question.

jfmengels1··on Tail recursion, but modulo cons
I think it could yes if you had a keyword for adding the guarantee.

If you didn't have a keyword, then all functions would have to be made stack-safe, which is I think a lot to ask the users in some cases, especially when the language doesn't give you all the tools for it (I think CPS does not work for instance in Elm, currently investigating that a bit).

If you have a keyword, then it would be as restrictive as you'd want it to be I imagine?

jfmengels1··on Tail recursion, but modulo cons
Factorial was taken as an example (in this post) exactly because it is such a common textbook example, which also happens to be bad example in the sense that it is not stack-safe.

As for walking a tree, I agree, but this optimization does not work well with trees shrug, making lists a nicer example in my opinion.

As a teaching method, I feel that factorial is a relatively good example because it is fairly easy to grok in your head or on paper. Recursing through a tree adds a lot of mental overhead, so I feel like it could be a follow-up example to factorial, but it's probably too hard as an initial example. Also, switching to a stack-safe function using recursion is again much easier for factorial than it would be for traversing a tree.

jfmengels1··on Tail recursion, but modulo cons
Potentially yes. The question then arise: does it ever make sense not to add that keyword, and should you get linter/compiler warnings when it's not used? In which case, there will be little gain. My mind is not yet made up on this to be honest. I feel like it would be valuable, but it feels weird when I think about it some more.
jfmengels1··on Tail recursion, but modulo cons
Indeed, though from a conversation with the author, it's only implemented for a subset of what was described in the post, specifically only for data construction. (Conversation: https://twitter.com/let_def/status/1485313834764095488)
jfmengels1··on Disable comments make static analysis tools worse
This advice was for custom rules for a team, so it's about enforcing what the team has already agreed upon and understood the trade-offs, not anything the tool decided upon on its own and imposes on the team.
jfmengels1··on Disable comments make static analysis tools worse
Just to clarify: Since elm-review is a static analysis tool separate from the compiler, you can run and compile your program just fine without having to handle all the dead code warnings (which elm-review is actually very good at detecting https://jfmengels.net/safe-dead-code-removal/).

I myself personally tend to run elm-review when I'm ready to make a PR most of the times.

jfmengels1··on Why we chose Elm for Humio’s web UI
He is not, but he's still actively working on Elm. You can find his latest interview here: https://elm-radio.com/episode/open-source-funding
jfmengels1··on Why we chose Elm for Humio’s web UI
I couldn't say the same thing for even well-architected TS apps. There are important escape hatches that TS gives that make it unreliable, as summarized in this article: https://incrementalelm.com/tips/typescript-blind-spots/

Refactoring code or updating dependencies is and feels a lot safer in Elm than in TS, and doesn't require asking for every npm package author to add TS type definitions.

I'd also argue that TS/JS have the esoteric/cool features. Elm is a very simple language, complete enough to be able to write most programs, but small enough to give you a lot of guarantees about how the code will behave.

jfmengels1··on Why we chose Elm for Humio’s web UI
The issues you mention sound like bad usages of Msg. I recommend asking questions on the Elm Slack to try and figure out what the problems are!
jfmengels1··on Why we chose Elm for Humio’s web UI
With regards to Elm being battle-tested, I'd argue that we've had that battle, and we won it.

Elm may not be a good fit for every project out there, like when you need tight integrations with specific JS projects, but it will work well for most projects.

At this point, I'd personally be more interested in hearing about cases where Elm was NOT a good fit (and why) rather than where it is.

jfmengels1··on Why we chose Elm for Humio’s web UI
We have, and that's where we reach out to JS/TS through ports or webcomponents. We try to use Elm as much as possible since that's the simplest and the most reliable, but using JS/TS this way is fine in small quantities.
jfmengels1··on Why we chose Elm for Humio’s web UI
The blog website isn't written in Elm. We're using Elm for the product application, not for the blog or for https://www.humio.com/. I'll transfer the remarks though :)
jfmengels1··on Safe dead code removal in a pure functional language
Ah alright. That's an interesting technique! You can't do that in Elm, you'd have to rely on the technique I mentioned above and regular tests.
jfmengels1··on Safe dead code removal in a pure functional language
And that is exactly the reason why the tool from the article asks you for confirmation at every step. So that you can actually go and say "oh, no, I want to keep and use that".

But even if you do blindly accept each fix, the behavior of the program won't change.

jfmengels1··on Safe dead code removal in a pure functional language
Elm doesn't have asserts. Instead, what you'd do is to have the function return a potential error (what in Elm we'd call a Result).

so instead of

function a(b) { assert(b > 0); return b + 1; }

you'd do

a b = if b > 0 then Ok (b + 1) else Err "b was not > 0"

To then use the result of the function call, you'll need to unwrap the result, by handling the case where the function returned Ok, but also the case where you return Err

case a -2 of Ok b -> -- display the value b Err errorMessage -> -- display the error message

THis is the kind of technique Elm uses to ensure that you'll have no runtime errors in your code: by forcing you to handle the error cases. The nice thing is that the types can indicate whether something can fail or can't.

jfmengels1··on Safe dead code removal in a pure functional language
The article author wrote this ESLint plugin to do just that https://github.com/jfmengels/eslint-plugin-fp

then he (I) happily switched to Elm, because even with a lot of static analysis rules, it's really hard to avoid impure functions when a lot of the libraries and existing code use that, and sometimes even require that.

jfmengels1··on Safe dead code removal in a pure functional language
In pure functional languages (at least in Elm), what happens is that you have data that describes what should be done, instead of doing it directly.

is talk called "Effects as Data" describing that idea: https://www.youtube.com/watch?v=6EdXaWfoslc

jfmengels1··on Safe dead code removal in a pure functional language
Sure, but under some assumptions. Assumptions like that some piece of code won't be transformed by a macro, that reasonably looking code like `a.b` doesn't have side effects, etc.

It's not that it's impossible, but that 1% (or 5%, 10%, ???% depending on how the project is structured and whether it uses a lot of side-effects or dynamic properties) can be enough make your program crash if the assumption turns out to be wrong.

Another example that you could go for, is can you determine whether a property of an object is used or not. If you have a language like JavaScript where you can do `object[propertyName]`, that turns out to be very hard. In a pure functional language, that is comparatively pretty straightforward to detect.