3 ms·
> Elm code is boilerplate heavy, it's a trade off you guys have made to make the language simple. I just straight-up disagree with this. If Elm added Haskell-s
by rtfeldman 10y ago
> Elm code is boilerplate heavy, it's a trade off you guys have made to make the language simple.
I just straight-up disagree with this. If Elm added Haskell-style typeclasses today, and we refactored our whole code base at work to use them, I bet it would save us less than 1% LoC.
This is such a weird thing to try to respond to. It's like a group of people started insisting that JavaScript's big problem is all the parentheses, and accusing JavaScript developers of sticking their fingers in their ears about the most obviously glaring weakness in the language.
What reasonable response can anyone make to that claim, except "I really don't think that's what the language should focus on improving?"
- iopq 10y agoYes, that's true, but I bet you some of the functionality that you wrote can be factored out into a more generic library that applies to everyone's use case. So it could be that half of your code is "library" code that could be open sourced - if it could be written generically with typeclasses. For example, Rust has typeclasses (called traits) and Rust has a lot of libraries that do the right thing for you. fn accumulate<'a, T: Monoid>(tuples: &[(&'a str, &Fn(i32) -> bool)], i: i32) -> Option<T> where T: From<&'a str> { tuples.iter() .filter(apply(second, i)) .map(first) .cloned() .map(<&str>::into) .fold1(T::op) //op just concatenates, but Cow<'a, str> does not satisfy Add } Here, the functions first and second are taken from tool.rs, fold1 is from itertools, the type Monoid and the function op is taken from monoid. I did have to write the delayed apply function myself, though. It's definition is: fn apply<A, B, C, F, G>(mut f: F, a: A) -> impl FnMut(&B) -> C // must still be `for<'r> impl FnMut(&'r B) -> C`, because that’s what filter requires where F: FnMut(B) -> G, // must not be `for<'r> FnMut(&'r B) -> G`, because regular functions do not implement it G: FnMut(A) -> C, B: Copy, // for dereferencing A: Clone { move |b| f(*b)(a.clone()) // this must do any bridging necessary to satisfy the requirements } I think that could also be in a library somewhere
- rtfeldman 10y ago> I bet you some of the functionality that you wrote can be factored out into a more generic library that applies to everyone's use case. Of course. We publish quite a few such libraries, in fact. :) Search for "NoRedInk" on http://package.elm-lang.org http://package.elm-lang.org
- kornish 10y ago> This is such a weird thing to try to respond to. It's like a group of people started insisting that JavaScript's big problem is all the parentheses, and accusing JavaScript developers of sticking their fingers in their ears about the most obviously glaring weakness in the language. That's a straw man which isn't directly analogous to the question of typeclasses. The reason is because parens are a syntax concern, which is understood at this point to be largely a matter of personal preference. Typeclasses are a language semantics matter. They could add new levels of reuse for identical operations over different types, and they've done exactly that for other languages. > What reasonable response can anyone make to that claim, except "I really don't think that's what the language should focus on improving?" Well, the burden of proof should be on the proposer: that the feature is useful. A good next step would be for someone who's interested in persuading you of the importance of typeclasses to pick concrete examples from NoRedInk's open source Elm and show you how they could be improved, disproving your hypothesis that typeclasses wouldn't really help. (edit: removed redundancy around "burden of proof")
- rtfeldman 10y ago> Well, the burden of proof should be on the proposer: that the feature is useful. A good next step would be for someone who's interested in persuading you of the importance of typeclasses I agree! That would make for a much more straightforward discussion. :)
- leshow 10y agoAs an example, I see code all the time with many showX functions whose sole purpose is to turn come ADT into a string, this is the kind of boilerplate that would be reduced with some kind of abstraction mechanism. Same for map operations, fold, etc. Then there's other things that would benefit from further abstraction, like being able to compose apps or update functions without boilerplate. These are just a few examples. What else do you need for it to feel like abstraction beyond simple functions is a useful feature?
- rtfeldman 10y ago
- curried_haskell 10y agoThe ridiculous comparison with parens only hurts your message. I think a more apt comparison is comparing Elm to Go missing generics. Without do-notation I imagine that elm code is filled with a lot more awkward case branching.