Live data from Hacker News

Elm in Production: 25K Lines Later

charukiewi.cz

271–278 of 278 posts

Re: Elm in Production: 25K Lines Later

#271

Earlier quoted context omitted.

> The simplest way to do BasicAuth in Haskell isn't Servant. I feel like you're intentionally misinterpreting what I'm saying. True, I re-read what you wrote, and argh . I need to learn to read. > As for resources, here's a great intro to type-level Haskell: > That's the kind of thing you need to know. So, we're basically returning to the root of my complaints > I doubt the average JS user knows how V8 optimizes exec…

> I doubt the average JS user knows how V8 optimizes execution of code, or whatever. That's what your insistent complaints about type theory amounts to: [...] Only a couple of people working on the compiler [use type theory]. > Wait. Are you telling me now is that writing a BasicAuth implementation in a "simple library that doesn't require you to have a PhD in type theory" is on the same level of complexity as knowin…

> I'm saying that knowing enough to be able to add big new features to the Haskell compiler, like the computer scientists who drive GHC development, is similar to knowing how V8 works. :)

Once again: THIS IS NOT WHAT I'M COMPLAINING ABOUT

I wonder if you have enough good faith to even see what I'm talking about.

Re: Elm in Production: 25K Lines Later

#272

Earlier quoted context omitted.

> Speaking from experience, zero. You can just treat them as syntax, like the largest proportion of every other language, but with the opportunity of actually being able to write things like that yourself later. So, basically, "learn this thing without understanding what it does" :-\ Reminds me of teaching Java to newbies: "oh, just type this syntax, you have to memorize it, don't worry about it". > Definitely less t…

>> Speaking from experience, zero. You can just treat them as syntax, like the largest proportion of every other language, but with the opportunity of actually being able to write things like that yourself later. > So, basically, "learn this thing without understanding what it does" :-\ > Reminds me of teaching Java to newbies: "oh, just type this syntax, you have to memorize it, don't worry about it". I don't think…

Let's consider this quote:

--- start quote ---

> :> and : You can just treat them as syntax, like the largest proportion of every other language, but with the opportunity of actually being able to write things like that yourself later.

--- end quote ---

This is exactly what's recommended: just blindly type these things, your understanding is not required.

It becomes worse. Link: https://news.ycombinator.com/item?id=14890937

You need 10 language extensions to implement the simples things. Answer to that complain?

Oh, five of them are just workarounds [so, just blindly copy-paste them]

Re: Elm in Production: 25K Lines Later

#273

Earlier quoted context omitted.

TIL there's some "idea of a monad". Basically this is (in my mind) what's wrong with Haskell: it's overly concerned with the Platonic ideal. Meanwhile that one page on jargon has shown me that I effortlessly implement any and all of those things daily (and understanding what I'm doing) without the need to understand "an idea". I just use the tool that solves the problem. If someone insists on calling this "monadic co…

> Basically this is (in my mind) what's wrong with Haskell: it's overly concerned with the Platonic ideal. I read this and I think what's got you rustled here is that Monad is such a generic concept. It's quite higher level and so you can do novel things like write functions that don't know how they're executing, just that they are. As an example: -- Config is a typeclass that enables getting a -- keyval from a confi…

Thank you for examples.

I have one complaint though:

> Doing this in OO is really, really hard to get right,

Why do you equate FP with monads? Moreover, why do you equate FP with Haskell/Purescript (statically typed FP with monads)?

Re: Elm in Production: 25K Lines Later

#274

Earlier quoted context omitted.

> They allow you to edit code without the aforementioned released-last-week test runner having to check all your code after a big refactor. Oh wow. How did I ever live with big refactorings before? > There are tons of nonsensical definitions that fit that which are going to become very unpleasant to use quickly. I recently learned that, apparently, I've been using "monads" and "monadic composition" for years now, nev…

The unpleasantness arises when writing Monad instances that don't follow the laws. Setting your disingenuity aside, try using xs >>= f = concat (reverse (map f xs)) or Array.prototype.chain = function (f) { return reverse(this.reduce((acc, it) => acc.concat(f(it)), [])) } (I don't know how JS works, but you get it) instead of xs >>= f = concat (map f xs) and enjoy refactoring your code, blissfully and consciously ign…

So, what problems will I experience while refactoring this code (if I ever wrote it)?

Re: Elm in Production: 25K Lines Later

#275

Earlier quoted context omitted.

The unpleasantness arises when writing Monad instances that don't follow the laws. Setting your disingenuity aside, try using xs >>= f = concat (reverse (map f xs)) or Array.prototype.chain = function (f) { return reverse(this.reduce((acc, it) => acc.concat(f(it)), [])) } (I don't know how JS works, but you get it) instead of xs >>= f = concat (map f xs) and enjoy refactoring your code, blissfully and consciously ign…

So, what problems will I experience while refactoring this code (if I ever wrote it)?

It won't satisfy the properties you've come to expect from the implementations you know for lists, optionals (Maybe), and so on.

Suppose you're going over some code, where you have something of the form

   xs >>= someFunction
(where xs is a list) and you change someFunction to "return":

   xs >>= return
Then you'd expect, from experience, that you can rewrite this to just

   xs
(which you can check works with all the monads you know about) but that doesn't hold for this wonky definition of the Monad instance for lists. Indeed, note that return for lists has the definition

   return x = [x]
so, with our bad >>=,

   [1, 2, 3] >>= return
   = concat (reverse (map (\x -> [x]) [1, 2, 3]))
   = concat (reverse ([[1], [2], [3]]))
   = concat [[3], [2], [1]]
   = [3, 2, 1]
which is not the same as [1, 2, 3].

https://wiki.haskell.org/Monad_laws

Re: Elm in Production: 25K Lines Later

#276

Earlier quoted context omitted.

> Basically this is (in my mind) what's wrong with Haskell: it's overly concerned with the Platonic ideal. I read this and I think what's got you rustled here is that Monad is such a generic concept. It's quite higher level and so you can do novel things like write functions that don't know how they're executing, just that they are. As an example: -- Config is a typeclass that enables getting a -- keyval from a confi…

Thank you for examples. I have one complaint though: > Doing this in OO is really, really hard to get right, Why do you equate FP with monads? Moreover, why do you equate FP with Haskell/Purescript (statically typed FP with monads)?

The use of monads is a side-effect (ha!) of committing to purity throughout a language, and that's what FP is being equated to: pure statically-typed FP.

(You can argue about how justified that is, of course. I'm not going into that, but you might want to see what John Carmack has to say[0]. No, he doesn't end by saying "we should all convert to the church of Haskell now", but he does talk about how large-scale game programming refactors are made easier when you're working with no (or very disciplined) side effects.)

Monads are not the only way to deal with effects while keeping purity, although they were the first discovered and so on: algebraic effect systems as in Koka[1] (and as simulated in Idris or PureScript) are another alternative. Koka infers effects, so it's probably easier for a C-family programmer to pick up (I know little about it, though).

[0]: https://www.youtube.com/watch?v=1PhArSujR_A

[1]: https://www.microsoft.com/en-us/research/project/koka/

Re: Elm in Production: 25K Lines Later

#277
post #171

Earlier quoted context omitted.

Your argument seems to be that "Real World Haskell" uses obscure features that I and many others don't understand, thus Haskell is complex. This is true if it is (a) impossible to write "Real World" Haskell without using these features and (b) that these features are truly complex and not just unfamiliar. An alternative hypothesis to (a) is that Real World problems can be solved by simple Haskell, but more sophistica…

> OTOH, learning new things can be fun and there's at least a small hill of anecdotal evidence that these things can pay their way at times. Life is finite, number of things to learn is near-infinite. Do I have the lifetime to learn 10 Haskell language extensions to understand how the most basic piece of code works?

Why are you asking me?

If it's to imply that the answer is "obviously not" so as to project it to other readers then why are you trying to answer for them?

Clearly others have decided that what you suggest is either unnecessary or worth it. But it's your choice.

Re: Elm in Production: 25K Lines Later

#278
post #240

Earlier quoted context omitted.

> Elm's type system will not catch this bug at compile time This is completely false. Elm's type system will force you to handle the decoding failure at compile time. The `decodeString` function has the following type: decodeString : Decoder a -> String -> Result String a Which means that when you call `decodeString`, it will return a Result containing either the decoded value or a String describing the error. This i…

You're just rewording what I said. The coder can simply ignore that string or make it empty, which can lead to a runtime failure if another module depends on a value being returned (think a runtime failure from a non-exhaustive pattern match). If they were a lazy coder in TypeScript, they'll be lazy in Elm (: So, no, what I said is not "completely false"

I would dispute the idea that "if they were a lazy coder in TypeScript, they'll be lazy in Elm". The fact that Elm forces you to at least think for a moment about how handle the failure case is a good thing. Even if you're inclined to take the path of least resistance, as probably most of us programmers are, what does that actually look like?

You have one case branch that looks like:

  GotUserList (Ok userList) -> ...
and another that looks like:

  GotUserList (Err _) -> ...
Since we need to pattern match on both types of the Result structure in our update cycle, there isn't really an opportunity to implicitly gloss over a failure to parse. Of course you can try to make the decoder super permissive, but this is harder than doing it the right way. If you're REALLY lazy, you can throw in "Debug.crash" in the failure case, but there's no general solution for throwing grenades at your foot :D
Post reply on HN