IBM releases Elm-powered app
discourse.elm-lang.org
discourse.elm-lang.org
That's one of the largest (and apparently most useful) Elm apps in the wild that I've heard of, and the fact that it exists and they had an overall good experience with it inspires me even more to try to learn and use Elm.
One thing I've found a bit weird about the Elm community is how common it is to highlight or even brag about the size of the codebases.
One of the reasons I have come to particularly enjoy Clojurescript on the front-end is because of how much code I don't have to write. I once ported an Elm app to Clojurescript and it was only one-third the line count for the same functionality, and generally a smoother experience.
I think some developers just love building up these huge, complex worlds and living inside them, and then telling others how big those worlds are.
It's nothing more than being happy that this somewhat academic and niche language is being adopted in the real-world.
Seriously, at this point IBM should fork a couple hundred thousand dollars just to know how anyone on their staff can recreate this in idiomatic java (or whatever OO language they want) and have you do it in idiomatic clojure/script. I'd be surprised if you managed less than 30k and very surprised if the OO implementation managed less than 100k.
Hard data on this kind of debate being hard to come by, we'd learn something from the experiment.
https://medium.freecodecamp.org/a-real-world-comparison-of-f...
Static type systems can absolutely catch logical bugs! Proof that a list is non-empty or that a reference is never null are simple examples.
> Types do not contain the real logic of your program.
Types can completely determine the logic of many parts of your program. In Haskell, I often don't have to write custom traversal code, it's selected for me based on the types.
> Types are somewhat useful for verifying data is passed around in the correct shape in a program
This is only the start of what types can do, try learning Haskell.
> but to say it prevents most obvious errors is naive.
No, naive is dismissing static type systems to the point that not even extra testing is done to compensate.
> Elm you will waste tons of time doing useless tasks like writing encoders/decoders and code that could be moved to macros in a more powerful language.
Elm's aim is to be a basic easy-to-learn language (no operator overloading etc). Personally, generic (polytopic) programming feels like a more elegant approach than macros. Haskell offers both.
Static typing can catch inconsistencies at the cost of structuring your code in a way that the type checker can understand. This is often at odds with making it readable for the human. A proof only has value as long as the human reader can understand it. Here's a concrete example of what I'm talking about: https://github.com/davidfstr/idris-insertion-sort/blob/maste...
An insertion sort written in Idris has over 250 lines of code that you have to understand to know that it's implemented correctly. A python version would have about 10 lines or less. I'd have much easier time guaranteeing that the 10 lines do exactly what was intended than the 250 lines of type specifications. Of course, you could relax the type guarantees in Idris as well, but at that point you accept that working around the static checker has benefit and it's just a matter of degrees of comfort.
In general, the more constraints you specify via types the more of your program logic moves into type specifications. What this really means is that you're writing a metaprogram that emits your logic. However, there's no automated checker for that metaprogram that you wrote using the types. You still have to understand it to be correct in order to know that it's doing what you want it to. At this point you're basically living in a programmer version of the Plato's Cave.
The real question is not whether you can do something using a static type system or not. The discussion has to center around how that compares to alternative approaches such as testing, gradual typing, and runtime contracts.
Your view on the role of types is unfortunate if you think term logic is simply mirrored at the type level (Plato's Cave). The Curry-Howard correspondence tells us to think of types as logical propositions with terms as their proofs.
The reality is that in most cases there's a cost benefit analysis regarding how much time you can spend on a particular feature and the strength of the guarantees.
>The Curry-Howard correspondence tells us to think of types as logical propositions with terms as their proofs.
Hence my point that you end up writing a metaprogram that emits the logic. Ensuring that the metaprogram is correct is a manual process. The more complex the proof, the harder it becomes to understand.
Consider Fermat's conjecture. It's trivial to state it, it's trivial to test it to be correct for a given set of inputs. However, proving it for the general case is quite difficult, and only a handful of people in the world can follow that proof.
This is a strawman, conventional static type system can't prove all general cases either and no body is saying that they do that. Yet, they being a superset of dynamic typing, they allow to have the same expesiveness as such by providing a bypass like 'Object' or 'any'.
I think that even the most liberal estimate on line count would be half what you typically find in Elm.
I’d say it’s more “look how many lines of code there are vs how many ways this could break in production”.
This will always be very different from your average ClojureScript/Reframe/Reagent app, which may or may not have fewer lines of code (in my experience they’ve been roughly equivalent), but vastly more opportunity for runtime errors.
Meanwhile, my team has been working with ClojureScript for years, and runtime errors are a really rare occurrence in my experience. Especially if you use Schema or Spec around the API between components.
However I think there's a difference between "with care, runtime errors are rare", and "by default, number of runtime errors is zero".
Of course, if it makes you feel better personally that's great for you and you should keep using it. However, if you're going to make wide sweeping claims regarding that, then they have to be rooted in more than just your personal experience and rationalizing.
Ultimately there are tradeoffs in how time is spent in both languages. Each developer will prefer different tradeoffs. I think in terms of net time spent on the whole dev cycle, it's hard to beat Clojurescript.
Clojurescript, on the other hand, has a novel system in place for handling runtime issues of any kind (types, values, whatever), because this is where it excels -- runtime dynamism.
And I don’t agree with it. I’m aware Elm doesn’t have dependent types.
Here's a concrete real world example of what I'm talking about:
>When I first wrote the core.async go macro I based it on the state monad. It seemed like a good idea; keep everything purely functional. However, over time I've realized that this actually introduces a lot of incidental complexity. And let me explain that thought.
>What are we concerned about when we use the state monad, we are shunning mutability. Where do the problems surface with mutability? Mostly around backtracking (getting old data or getting back to an old state), and concurrency.
>In the go macro transformation, I never need old state, and the transformer isn't concurrent. So what's the point? Recently I did an experiment that ripped out the state monad and replaced it with mutable lists and lots of atoms. The end result was code that was about 1/3rd the size of the original code, and much more readable.
>So more and more, I'm trying to see mutability through those eyes: I should reach for immutable data first, but if that makes the code less readable and harder to reason about, why am I using it?
https://groups.google.com/forum/#!topic/clojure/wccacRJIXvg
Another example of something that's trivial in a dynamic language, but difficult to do in a static one would be Ring middleware: https://github.com/ring-clojure/ring/wiki/Middleware-Pattern...
So really what you're doing with static typing is trading one set of problems for another. This is perfectly fine if those are the kinds of problems you prefer to deal with, but it's important to recognize that you are making a trade off as opposed to getting something for free here.
One aspect is "I refactored the code, fixed all the type-errors and everything works", another is "I don't know, what should I write here, compiler, tell me!" with typed-holes, along-side some nice search, such as hoogle (or elm's fancy search [1]) In simmilar fashion, I remember Elm was enforcing a version bump, if you break package public api.
On the other hand, you definitely are replacing one set of problems for a different set, and it is up to you to decide what kind of problems you like solving better.
For me, access to fast immutable data-structures seem to have the best return-on-investment, and easiest to introduce (i.e. even Javascript or Python have somewhat decent libraries for these).
Meanwhile, immutability as the default makes it natural to structure applications using independent components. This helps with the problem of tracking types in large applications as well. You don't need to track types across your entire application, and you're able to do local reasoning within the scope of each component. You make bigger components by composing smaller ones together, and you only need to know the types at the level of composition which is the public API for the components.
Spec [2] is a contract system that's often used to define API boundaries in Clojure. I find it provides an advantage over static typing because it directly focuses on semantic correctness. For example, consider a sort function. The types can tell me that I passed in a collection of a particular type and I got a collection of the same type back. However, what I really want to know is that the collection contains the same elements, and that they're in order. This is difficult to express using most type systems out there, while trivial to do using Spec.
Spec also facilitates stuff like hoogle [3].
[1] https://vvvvalvalval.github.io/posts/what-makes-a-good-repl.... [2] https://clojure.org/guides/spec [3] https://re-find.it/
But to show more of I really liked when developing with types, take a look at this slightly contrived example [1]. I once tried to refactor a medium size haskell code-base, and ability to just ask the compiler "Hey what should I put in here?" really made my life easier :)
[1] https://github.com/paf31/24-days-of-purescript-2016/blob/mas...
> "by default, number of runtime errors is zero"
And that's just a silly argument to make about any language and I hope Elm developers don't have false confidence about this.
It's a lot of lines, but how many characters is it?
- the ones you do get from your JS code – will be shown as console errors not involving Elm runtime in their stack trace
- guaranteed support for time-traveling debugger and model serializability. How would one do this in OCaml if it allows mutable data (possibly cycle dependencies), side-effects and JS FFI?
- better dead code elimination. All the code in Elm is pure
Basically, OCaml brings almost nothing to the table out of things Elm provides because it tries to suit everybody.
The ReasonML debugger supports time-travelling as one of its features.
The Bucklescript compiler that backs ReasonML provides dead-code elimination.
Yes, but the question is: does it guarantee to be working or is it only "sort of" working? Can your view do side-effects? Can it call JS? If yes -- it will break soon.
> The Bucklescript compiler that backs ReasonML provides dead-code elimination.
I didn't say it doesn't. I said it will be way more poor than the one Elm has. I don't have the link, but Todo app in Elm weights less than the one made in React, that's how good it is.
Tooling isn’t mature. IDE plugins, time travel “debugger” : they cannot compare yet with our usual Dev XP for TS
The language has its warts, but I would use it if it were not for the poor project management and support.
I.e. https://github.com/janestreet/ppx_let kinda looks like let! bindings in F#
And to be fair it's the best documented platform for web development I have worked with. Have you looked at documentations of random npm packages lately? No, fun.
1. An official guide: https://guide.elm-lang.org/ - with a Hello World followed by all the basics.
2. Great docs https://elm-lang.org/docs with search function. Most package I see have all the functions described with examples etc. E.g. https://package.elm-lang.org/packages/elm/browser/latest/Bro...
3. A subreddit and discourse chat where beginners can ask questions and get good answers.
It is available for [Haskell](https://github.com/ajnsit/concur), [Purescript](https://github.com/ajnsit/purescript-concur), and [Javascript](https://github.com/ajnsit/concur-js) (so no need to learn a new language), and also allows using external React components. The Javascript version uses Async Generators as a substitute for Monads.
With Concur, you can implement the entirety of Elm architecture with a few lines of idiomatic code.
Purescript or Haskell -
elm render update = go
where go st = do
action <- render st
go (update st action)
Or in JS - function elm(render, update){
var go = async function*(st) {
action = yield* render(st);
yield* go(update(st, action));
};
return go;
}I didn't consider elm's architecture as the main value proposition -- if you squint it looks just like every other data management model for component-based approaches these days -- flux, redux, etc all work in a similar way, +/- immutability.
Hopefully people aren't out there thinking that Elm has done something to magically make it much harder to write runtime errors -- they added a powerful ergonomic-where-possible type system.
If developers out there are still thinking types are "bad for JS" or that using types in code is weird/unnecessary, they might be suffering from Blub[0], and need to go out and see what other languages are doing maybe widen their perspectives. Not every language with a good type system looks like Java/Dart/Typescript/etc (some people can even argue that Java doesn't have a good type system) and I often meet engineers who think adding/checking types basically means making javascript into java.
Concur was first written in Haskell, so it's got the Functional Programming part down :) The other interesting part was TEA, which is hard to simplify further, but I think Concur's model manages to do that while simultaneously being more powerful.
Edit: I don't know what gave you the impression that I don't like types. I love types! I wish JS had more of them. I write Haskell/Purescript (and Javascript) in my day job.
Didn't know that, weird how it's come full circle in a way, I don't think people would consider Elm as approachable as they do now if React, Flux and resultingly redux hadn't gotten so popular. There was also a bit of a hype train behind FRP for a while but that seems to have petered out a bit.
To be fair I'm not an Elm expert but try to keep up with it, I have yet to write something big in it, but I absolutely believe the hype because the hype isn't hype, those of us that are writing or at least peeked at the Haskell/ML world have been living in this world up until now.
> Edit: I don't know what gave you the impression that I don't like types. I love types! I wish JS had more of them. I write Haskell/Purescript (and Javascript) in my day job.
Sorry I didn't mean to imply that you don't, I will go back and edit my comment -- I meant I still run into that sentiment, most recently at a meetup last month. It's not like I don't understand it, you can move faster without type checking but a lot of times that just means letting code with silly bugs through that you're going to find @ runtime.
Oh yeah absolutely. And also, FP and immutability makes everything much easier to understand. Getting new devs making changes to 50k lines of JS is much much much worse than with a Haskell/Purescript/Elm project of similar complexity.
Concur has a very uniform programming model where you do everything by composing widgets. `elm` is a widget. `render` also is a widget. As such both can perform arbitrary async effects, and they take place inside event handlers, or inside lifecycle methods like componentWillMount. Concur takes care of managing that for you.
So to log all actions to the console, you can add a logging call to `elm`.
elm render update = go
where go st = do
action <- render st
liftEffect (log ("Action - " <> show action))
go (update st action)
Meanwhile, the render function itself can be a widget which performs side effects - view = do
evt <- button [onClick] [text "Click me"]
liftEffect (log "Button was clicked")
return evt
There are lots of examples of effects in the Concur repo - Take a look at some running examples here -https://github.com/ajnsit/purescript-concur/blob/master/exam...
And running demo -
I think Elm isolates its “views” much more, but concur might be easier (less boilerplate). I will definitely give it a try now, sometime.
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, div [] [ text (String.fromInt model) ]
, button [ onClick Increment ] [ text "+" ]
]
The html elements themselves are Elm functions. Code looks like data. Nice. Now considering Elm to be potentially useful tool to know.Isn't this true for like, 95% of languages? Yes, Elm breaks from it's Haskell heritage in this regard, but this is a very common lack of feature.
I wonder what others are? Would like to try them.
https://reagent-project.github.io/
And check out re-frame as well, which adds on tools for handling data flow and many other things:
the real world implementation in re-frame up on https://github.com/gothinkster/realworld has excellent comments and is a great way to learn it after the docs
No square or other brackets, just indentation defines the structure and it's beautiful. The only oddity is that 'div' has to be written as 'tdiv'. Here is an example from the Nim forum's frontend code: https://github.com/nim-lang/nimforum/blob/master/src/fronten...
```
val model = div(
button( onClick := decrement )( "-" ), // decrement is typechecked as being a function of event
div( float := float.letf )( model.toInt ) //left float is typechecked and hence the misspelling is caught at compile time so big changes can be made with confidence
)
```However that was all for static UI though. Writing Elm app is still a pain if you are not a Javascript expert. Elm's implementation of the web API is minimal and the progress is extremely slow. In addition, most function that's in libraries in Javascript's ecosystem can not be directly used as you have to write Ports, which requires a lot of Javascript experience.
Another things is that in Elm the state of the whole application is very visible. Typically just by looking at data structures and message types one gets how things work. The code just fills details.
// Stateful
state = {buttonClicked: false}
render() {
if(!state.buttonClicked) {
return button({text: "Click Me", onClick: {state.buttonClicked=true}})
} else {
return text("Thanks!")
}
}
vs. // Implicit state
render() {
yield button({text: "Click Me", onClick})
yield text("Thanks!")
}To test render() in the clicked state with the explicit state I can call it with the corresponding state. With the implicit state at the very least I have to write a driver to run render() into the clicked state and then test the next state transition.
To understand the effects of the code on other parts of the application with the explicit state it is sufficient to look at the definition of the state. The implementation of render is only relevant if one wants to look at details. With the implicit state I have not only understand what render() is doing, but also understand how to properly call it from other parts of application. I.e. what happens when the render is called the third time?
In my hypothetical implicit state framework - A widget is composed of a sequence of steps, each of which is an independent widget. So it's easy to write invariant properties for each step -
For (text "String") it's guaranteed that the widget never returns a value or raises an event. i.e. the type is
forall a. Widget a.
So the issue of calling render a third time never arises.Would you also say using "goto" is easier because it's a simple jump, vs. having to understand how while/for loops work?
Besides, your example get much of its gains by hiding the behavior of that 'if' statement than by hiding that 'buttonClicked' stores the button data.
Sure, I'm not going to argue the meaning of "state". You know what I mean. Hiding internal state is good for abstraction.
> Besides, your example get much of its gains by hiding the behavior of that 'if' statement than by hiding that 'buttonClicked' stores the button data.
The if statement is intrinsically linked to the boolean state. If your render function forgets its implicit state on every update, then it needs to painstakingly analyse an external state and recreate its internal state. That's a cost which can be avoided.
The biggest drawback of the explicit state is that the separated GUI stages has to be named so the code can refer and match on them. This naming requires to spend mental energy when writing the code and is the reason behind complains about extra boilerplate in Elm.
In implicit state the stages are anonymous and hidden behind a semicolon (yield statements in your example). So it is faster to write code. Yet these nameless yet present states exist and makes much harder to grasp the code. One has to recover the states from the code, not from declarative description as with the explicit state.
You've used an example similar to a continuation, what is explicitly about flow control. Unless you are suggesting appropriating flow control into data (because you will need an interpreter) means that everything is "state".
I don't think that 'buttonClicked' value will make into the page state of an Elm program.
Also, the framework I described is only partially "hypothetical". [Concur-js](https://github.com/ajnsit/concur-js) gives you almost the same syntax and semantics. So you can try it out yourself :)
This is a common criticism of Elm, and I've never understood it.
The criticism seems to be that "Elm is bad because I still need some JavaScript, and JavaScript is dangerous."
Like, what's the alternative? More JavaScript?
[@bs.val] external pi : float = "Math.PI";
let tau = pi *. 2.0;
[@bs.val] external alert : string => unit = "alert";
alert("hello");
Elm was trying to make it very hard to use JS in Elm which is always a bad idea when you are a transpiled language. Clojure is so popular because you have access to most of Java and the libraries written in Java. ReasonML makes super easy to use JS (or other languages, same FFI interface) while being an ML family language just like Elm. For me ReasonML is clearly the winner of type safe JS for these reasons.Your code will produce runtime errors which will be rendered into console with ReasonML runtime guts in it. I would disagree that this is in any way superior to Elm's promise of no runtime errors, and JS via ports having no runtime in its errors.
That is why I use Elm, and not some other compile-to-JS language that allows me more freedom.
I don't want freedom. I want constraints.
Freedom is the rope with which I can hang myself.
Constraints keep my bug tracker silent.
> Freedom is the rope with which I can hang myself.
If you'd like to, why not? It's up to you. You're not forced to do, though.
On the other side, being a hostage of some secret plans in "people in power" minds, you might be forced to do any kind of staff. New constraints are here and they're enforced on anyone. That's a catch with constraints, you can be OK with existing, but you'll never know what comes tomorrow.
Well, yeah. If I'd like to hang myself, I'd pick a technology with fewer correctness guarantees. As it turns out, that's not what I want. This is self-evident.
It's also not a valid criticism for you to say that you've found Elm doesn't "follow the common sense". This is too vague to be any kind of constructive criticism.
That's exactly what I'm talking about. I'd also like to pick up some "silver bullet", like Elm(if I got you right), for any new project.
Unfortunately, real world is usually a little bit more complicated than "I'm free to pick up any technology that I want. All browsers are the same, their behavior is consistent, mobile web is pure joy and all of our users know their plugins might cause an issue to our app, therefore they're disabling them when they launch our app".
Anybody who does webdev knows that. Different projects, different requirements(sometimes very, very strange), brand new requirements right before the release, deadlines, etc. There're lots of things you have to deal with to end up with a good website\app. Picking a language with nice "correctness guarantees", is not going to help you much.
There were times, long time before 0.19, when there were at least discussions on effect managers, extending the type system, native modules were a nice escape hatch to fix your problem at hand with nasty browser bug or even Elm runtime issue. Those were times when I was so excited to use Elm, did some tiny (sub)projects in it, did a workshop at the office.
Since then, many things have changed to the worse, imho. Some features were removed, not even deprecated. No public discussions, no roadmap, no bugfix releases, no escape hatches for special cases. But who cares what some random guy on the internets thinks :)
Don't get me wrong, I think Elm is a great experiment in the land of static languages, lots of great stuff is getting into mainstream languages(like Elm architecture, error msgs). I still hope we'll see the 1.0 version and things might get better in terms of feature stability, feedback and building things a little bit more complex than counter apps without hitting even more pain points than we have with modern JS\TS.
Nothing is a silver bullet. Never claimed it was.
> Anybody who does webdev knows that.
I am a web developer, and I disagree with you.
> Picking a language with nice "correctness guarantees", is not going to help you much.
That hasn't been my experience.
> Since then, many things have changed to the worse, imho
Exactly — it's your opinion. Removing surface area for runtime areas is a change for the better, in my opinion.
> building things a little bit more complex than counter apps
My businesses are more complex than counter apps.
That said, you could add effects and a JavaScript FFI using monads or algebraic effects. You could also get rid of a lot of boilerplate in the Elm architecture using existential types. It's a safe bet that the Elm developers know this. But all of these extensions would make the language less approachable. I think one of the reasons why Elm is doing so well is because it's not Haskell. :)
Also a little surprised you mentioned do notation; it's just syntax sugar after all :)
I have heard this sentiment earlier, and I believe that there is a better middle ground. Use a less restrictive platform and simply don't use features you deem too complicated. That's a better approach because as the developer becomes more familiar with typed FP, they would be able to use better and better tools at their disposal. i.e. the toolset will grow with their skill.
> Also a little surprised you mentioned do notation; it's just syntax sugar after all :)
Oh it's less of an issue, but syntax does matter a lot. I find that Monads become intractable for new devs without do-notation.
That's a fair point, and I agree, however this somewhat negates your previous point:
> Use a less restrictive platform and simply don't use features you deem too complicated. That's a better approach because as the developer becomes more familiar with typed FP, they would be able to use better and better tools at their disposal. i.e. the toolset will grow with their skill.
I can't say definitively, but you could argue that on a team, a more experienced developer might use more advanced features of a technology, which less experienced developers then have to just deal with. They might feel intimidated by that, and discouraged from working with the technology at all. I'm using "team" in a more abstract sense here too; it could be all the collaborators (existing or potential) of an open source project.
I'm not arguing the anti-intellectual position that everything should be dumbed-down. I just believe — as you said — there is some middle ground, which also isn't universally applicable.
Actually in practice that's much less of an issue when using typed FP. I've found that it's easy to modify parts of code which you do understand the implementation of, while still being able to use the interface of other potentially more complex parts. Of course YMMV.
Elm disguised as a beginner friendly language for web front-end, which is not true with the case of ports. Where you need to be fairly familiar with Javascript.
The Elm community also advertise a lot on the advantage of development happiness of Elm over Javascript, and mention the Javascript fatigue a lot. But the truth for a beginner is that you can't escape the Javascript ecosystem when using Elm, and sometimes it requires even more Javascript experience than using just Javascript framework like React to build something that require a web api that's not in the tiny list that Elm provided.
If web development is not someone's main job and they are just finding a tool with better dev experience to build some side projects, the fact that they need to design an interface for almost every external package is not aligned with their original reason to use Elm.
I don't understand. You're saying a codebase of 5% JavaScript demands more JavaScript experience than a codebase of 100% JavaScript.
This seems self-evidently false.
> If web development is not someone's main job and they are just finding a tool with better dev experience to build some side projects, the fact that they need to design an interface for almost every external package is not aligned with their original reason to use Elm.
Seems like the argument is Elm isn't ideal if you're not a programmer, because you can't cargo-cult it.
I think I'm ok with that.
A codebase of 100% Javascript does not usually mean 100% written by the app developer. If you are coding in react for some basic app, like some basic crud with react using existing backend with Firebase, it almost only require you to learn the some basics of react and Javascript syntax, and fill in the template. You can also use other modules by just follow their documentation when you need some extra functionality.
However in Elm Ports we are required to pass async messages for everything which is much harder. I am OK with the boilerplate for the JSON encoder and stuff, but I have to wrap around my head for how to write a port for lots of basic web APIs.
Port is hard even for people that familiar with Javascript. There are plenty of experienced Javascript programmers willing to dive into the source code of Elm to write native modules to avoid ports even. https://www.reddit.com/r/elm/comments/81bo14/do_we_need_to_m...
In addition, even the 5% of Javascript will eventually leads to the full Javascript stack, where Elm, without an official recommend JS stack, feels more like additional choice as a part of the JS fatigue. Beginners ends up looking up on browserfy/gulp/webpack etc and figuring out a way to integrate Elm in.
> Seems like the argument is Elm isn't ideal if you're not a programmer
I program daily for machine learning, and I have used many programming languages. But Javascript is not the language that I want to dive in too much, which it is the main reason I learn Elm. If your requirement of being a programmer is having a job as a software developer, then I am not. But I think a language with an aim of going into education and scientific computing shouldn't limit itself to that. https://www.youtube.com/watch?v=uGlzRt-FYto
I enjoy Elm. It is one of my favourite programming language. But I have not gotten anything done with it mainly because of ports. If I am pursuing a career in front-end related development, I would dive into Javascript and build stuff. I understand the decisions from Evan and friends and I am just thankful for Elm as it is, there is no right for me to demand anything anyway.
[edit: formatting]
Doesn't look like it.
So the best use would be for designers who code, basically unifying frontend design and engineering.
Elm is the opposite, it's focused on the whole which you then use as the basis for parts at actual design time (thinking about layout and hierarchy).
So in a way Elm is about form following function (creating visuals from existing functionality), while most of the other environments are focused on function following form instead (creating functionality based on existing visuals).
IMHO you can do design-first process with Elm just like with React. There is no Storyboard equivalent that I'm aware of, but I never found it useful enough but maybe it is, for toolkit/library designers.
I have found that I work differently depending on environment. I do model/types/functionality first if working on my own, but in a corporate environment I typically get designs handed together with some kind of specification, so there I often do "design-first".
That's the best way to handle this I think. I didn't mean that you can't do specific workflows in either framework or language, just that there is a "native ideal way" of how things are done.
Philosophically it's an interesting topic, because there are many arguments for and against either method. It's also way bigger than programming, it's about evolution itself.
And you get code sharing across client and server as its just plain old scala. I believe elm is not big server side.
And if so: In production? Does it work? Do you trust non-programmers with it?
(I know the Elm people don't like jokes about the email client. Tough; they should have picked a name that wasn't already used.)
But Pine Is Not Elm.
I wonder how many of today's Linux users don't get why the editor is named nano. The fact that you can trace the name back to "electronic mail" is my favorite command-name joke in an environment full of them.
(If you missed the chain, it was
1. "electronic mail" = "elm"
2. "pine" as a joke on "elm" -- though I believe they deny the "PINE Is Not Elm" derivation, it's still pretty clearly a reference to elm
3. "pico" the editor as "PIne COmposer"
4. "nano" as a joke on "pico".)
I think that's what happened with Clojure and people coming up with jure puns on it (compujure, etc).
https://github.com/Raynes/lein-newnew/blob/master/src/leinin...
I think maybe this is when you decide 'maybe our language has failed'. Or at least admit it's a toy language that hasn't been properly engineered to be effectively used commercially. When it's a 'worth mentioning' when a single app has been written in it by some dying company.
I mean, imagine if we had a headline on the frontpage of HN for every app written in C or C++ or Java or Python (or Objective-C or Swift or C# or even Visual Basic or Rust)
Steve Yegge said it best almost 10 years ago: https://steve-yegge.blogspot.com/2010/12/haskell-researchers...
Functional languages are great toys but nobody uses them to get work done, almost without exception.
I run my own businesses on functional programming languages (Haskell and Elm) almost exclusively.
100% of my income comes from the three software products I own, all primarily written in Haskell.
You're displaying a pretty amazing level of ignorance here.
NewBusinessMonitor[0] is a tool for marketing your products/services to businesses in the UK. This company is a bootstrapped SaaS, built and run by just me. It's been taking money for over a year.
Comparestack[1] is a price comparison platform. Our first product is Moneygains[2] — a way for residents of Northern Ireland to switch to a better deal on their home electricity. I'm building this with a partner — he's taking care of all the business stuff.
I have a third in the reinsurance space, and it has taken funding. I'm not going to talk about this one so much for the time being — it's still in stealth mode.
[0]: https://newbusinessmonitor.co.uk/
> Steve Yegge said it best almost 10 years ago
That reads like a Register article. It's just a bit of fun.
Just because you don’t use functional languages for serious commercial work and don’t personally know anybody who does, doesn’t mean the rest of us don’t too. Plenty of us use functional languages for serious commercial work, now or in the past. I’ve persobally used ClonureScript and know plenty of people who use Clojure. I know people who use Haskell. Jane Street famously use OCaml. Lots of people use Scala. Clearly an IBM team uses Elm. I mean, the article itself is a counter example to your statement.
IBM, in my mind, is a massive dinosaur. To know that some group there was able to make a consumer facing product using the latest tech is cool. Definitely gives IBM a better favorability rating in my view.
(Note, I'm not convinced that IBM is quite so ... obsolete... as this discussion implies, either.)
Despite the fact that they have a very bullish minority in the industry doing some very serious and lucrative work using them.
See for example Jane Street and Ocaml.
The fact that functional languages are not yet "mainstream" is more of an artefact to two things unrelated to their capability as languages in an industrial setting:
a) Historical baggage. Industry has always taken the first tool it has come up with, declared it the "professional tool", which has become a self fullfilling prophecy then. Despite when looked from historical perspective, there is no technical reason why the chosen language was best among many. See for example C, C++, Java, and my favorite example JavaScript (ship it! 9 days is quite enough to make a language).
I.e. industry has taken anything that creates an abstract syntax three that can be transferred to the chosen execution context, and maked it work by adding tooling and education, no matter how crude the language itself was.
b) Lack of industrial quality tooling. See a). Industrial quality tooling is often a sane prequirement to choose a language for a project. There might be instances where you feel you might want to hire a legion of developers, and then you choose probably one of the most popular languages because it has tooling and it has a large number of candidates who know the language.
Note: neither the fact that the language has tooling, nor that is popular, does mean it's the "best" for an arbitrary scenario.
https://reasonml.github.io/blog/2017/09/08/messenger-50-reas...
"Which Team's Next?
We believe in iterating on/alongside product teams in order to create the best infra. The product teams' and open source folks' feedback has changed our strategy a few times, for the better. As of today, Reason and BuckleScript are also deployed on a WhatsApp internal tool, Instagram Web (small scale), plus some critical Ads internal tools. We'll be working closely with these teams over the next year."
IBM writing an app of this size in Rust would definitely be headline-worthy.
For other languages you list, it's not, but only because they're already well-established, and have been for decades. But it could have been a headline when they were new and unproven.
Definitely not the most important thing on the list, but I use Vim to code so IDE integrations mean absolutely nothing to me. I hate IDEs. To companies and teams that can't go to the bathroom without an IDE, that may be a deal breaker. Either way, it is good information to have.
As an aside, of all the things I judge a job offer on, whether or not they use IDEs is pretty far down the list.
I can get Visual Studio to behave like VIM and vice versa probably.
I find it interesting that people sometimes hold this in high regard.
For example in Elm, all the nice error messages can appear next to the line, and all the case-of statements can be auto-completed according to the type definition, it all adds to an overall better coding experience.
Doesn't this already happen almost every day for Rust and Go?
Whatsapp was written in a FP, as is a large segment of Cisco router control plane. React arguably is strongly pushing towards a FP subset of ECMA6.
As somebody who's been working with Clojure professionally for nearly a decade that's big news to me. Also, you might be surprised to know that it's used by companies like Walmart for critical infrastructure https://clojure.org/community/success_stories