
IBM releases Elm-powered app - quickthrower2
https://discourse.elm-lang.org/t/ibm-releases-elm-powered-app/2364
======
savanaly
In a comment below the main post they say that the app they wrote is
approximately 45,000 lines of code over 170 Elm files.

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.

~~~
hellofunk
> In a comment below the main post they say that the app they wrote is
> approximately 45,000 lines of code over 170 Elm files.

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.

~~~
davidgrenier
I think you should read this as being an otherwise 150kloc project in Java.

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.

~~~
yogthos
In this comparison of a minimal "real world" app comparison, Elm version has
around 3 times as much code as ClojureScript.

[https://medium.freecodecamp.org/a-real-world-comparison-
of-f...](https://medium.freecodecamp.org/a-real-world-comparison-of-front-end-
frameworks-with-benchmarks-2018-update-e5760fb4a962)

~~~
willtim
An apples and oranges comparison. Any difference would surely be made up by
all the tests one would have to write to be sure the clojure code was free of
basic errors.

~~~
yogthos
That's a completely baseless assumption. I have not found the need to write
any more tests in Clojure than I have in statically typed languages. The only
tests my team ends up writing tend to be end-to-end specification tests, and
you would want to have those in any serious project regardless of type
discipline.

~~~
willtim
Tests prove the presence of bugs not their absence. You _should_ be writing
more tests if you have no static type system, in order to find the bugs that
you would otherwise prove don't exist.

~~~
bgorman
A static type system like Elm doesn't fix logical bugs like wrong indexing,
wrong predicate etc, it just finds issues with types. Types do not contain the
real logic of your program. Types are somewhat useful for verifying data is
passed around in the correct shape in a program, but to say it prevents most
obvious errors is naive. Not to mention in 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.

~~~
willtim
> A static type system like Elm doesn't fix logical bugs

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.

~~~
yogthos
Haskell was my first FP language, I used it for about a year, and worked with
Scala briefly after. My experience is that you're really trading one set of
problems for another in practice. Static typing can guarantee that you avoid a
certain class of errors, but it often results in code that's longer and more
difficult to understand opening opportunities for different kinds of errors.
There is absolutely no empirical evidence to suggest that the trade off is
strictly superior in practice.

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...](https://github.com/davidfstr/idris-insertion-
sort/blob/master/InsertionSort.idr)

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.

~~~
willtim
Sorting (TimSort) was broken for many years in Python. It was good old-
fashioned logic and theorem proving, not tests or runtime assertions, that got
it fixed. There is merit in proving properties of any critical implementation,
no matter how difficult. However the gist you referenced looks to be someone's
learning effort, so hardly a model example.

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.

~~~
yogthos
Sure, you can use formal methods to prove properties that are hard to test.
The point you seem to have missed is that it takes a lot of effort to do that.

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.

~~~
maxilulu
> onsider 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'.

------
hellofunk
Now that we have ReasonML, which has a more predictable and sustainable
release cycle, and large support, as well as functional programming from OCaml
and smoother JS interop when that's desired, what does Elm still bring to the
table? When Elm was originally developed, there wasn't a viable alternative
for those who wanted good statically-typed FP in the browser, but it would
seem now that new apps in this style of development have far more choices with
generally fewer pain points.

~~~
adgasf
I would take F# + Fable over Reason since Reason doesn't have computation
expressions or do-notation

~~~
a-saleh
I think you could replicate some of these with ocaml_ppx system (looks like
macros over ast?)

I.e.
[https://github.com/janestreet/ppx_let](https://github.com/janestreet/ppx_let)
kinda looks like let! bindings in F#

------
haskman
Shameless plug - I'm trying to improve upon Elm and React's programming model
with my Concur UI framework. Its programming model is a bit unusual, it uses
Monads to sequence widgets in time, but it is designed to be extremely simple
to use, and you don't need to actually understand Monads to use it. An
advantage is that it's not artificially restricted like Elm, and allows you to
use advanced Functional Programming tricks when you can and want to.

It is available for
[Haskell]([https://github.com/ajnsit/concur](https://github.com/ajnsit/concur)),
[Purescript]([https://github.com/ajnsit/purescript-
concur](https://github.com/ajnsit/purescript-concur)), and
[Javascript]([https://github.com/ajnsit/concur-
js](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;
        }

~~~
hardwaresofton
I've always thought that Elm was like Purescript in the way that it was just
another way to bring the good parts of Haskell (a good type system) into JS.

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.

[0]: [http://wiki.c2.com/?BlubParadox](http://wiki.c2.com/?BlubParadox)

~~~
leshow
Elm isn't a general purpose programming language. You can only write web-apps
with it you can only use TEA (the elm architecture). In that way, the TEA
really is it's main value proposition.

~~~
quickthrower2
You can do more than that using ports, but it doesn't sit very naturally.

------
i_feel_great
This inspired me to look up the Elm docs, and came across this gem:

    
    
      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.

~~~
grenadier21
That's how literally every VDOM-based framework looks, including React. Elm
isn't special in this regard. It is special in many other regards, however,
and I appreciate it for that. It's also interesting as one of the few
languages that have parametric polymorphism but no ad-hoc polymorphism, which
leads to some interesting designs. I don't like how only the BDFL is allowed
to do certain things, like create new operators in external libraries, but
overall, it's a very pleasant experience.

~~~
lalaithion
"I don't like how only the BDFL is allowed to do certain things, like create
new operators in external libraries"

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.

~~~
grenadier21
Fair enough, but my main problem with it was that it existed, and then they
removed it, which was very sad.

------
fpoling
Elm is fascinating since it shows that with the right architecture functional
programming for GUI is possible without hatches like monads or hiding state in
closures or green thread stacks.

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.

~~~
haskman
I understand what you are saying, but - the whole point of abstractions is to
"hide state". For example, what is nicer to write/read? Pseudocode -

    
    
        // 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!")
        }

~~~
fpoling
What is nicer to test and maintain?

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?

~~~
haskman
Testing could be _much_ easier for the implicit state version. I've not
defined it, but you are assuming things about how the render function or the
implicit state behaves.

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.

~~~
dkersten
The explicit version we can understand how it works just by looking at it. The
implicit version we need knowledge about how your hypothetical framework
works.

~~~
haskman
Of course you need to understand how the framework works. But that's a fixed
cost vs. having to understand a program from scratch everytime when your
framework is not clear or powerful enough.

Would you also say using "goto" is easier because it's a simple jump, vs.
having to understand how while/for loops work?

------
yakshaving_jgt
> Ports == lots of boilerplate and “loose” typing

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?

~~~
StreamBright
Have you seen ReasonML?

    
    
      [@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.

~~~
yakshaving_jgt
I do not agree that it is "always a bad idea".

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.

~~~
gothy
I was(am? will be again?) a fan of Elm. Constraints can be helpful and even
liberating(in some sense). But that's something that should be balanced
carefully with other things, like rules\laws that are clear, universal and
follow the common sense. Unfortunately, during my Elm journey, I've found
that's not the case for Elm.

> 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.

~~~
yakshaving_jgt
> If you'd like to, why not? It's up to you. You're not forced to do, though.

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.

~~~
gothy
> 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.

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.

~~~
yakshaving_jgt
> I'd also like to pick up some "silver bullet", like Elm(if I got you right)

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.

------
tolmasky
Is there no way to try this without signing up? I even finally decided I'd
sign up and then was greeted with a form that required a phone number.

~~~
neurotrace
> The app is live here (requires registration)

Doesn't look like it.

------
deltron3030
What I find most interesting about Elm as a designer who also "codes", is that
because of its bottom up frontend philosophy (types first instead of
components first) it somehow assumes that the UI designer and coder is the
same person, that there is no clear designer to developer handoff where you
hand over a thought out design to implement. It's more the other way round,
where you'd hand over what you've come up with in Elm to a designer (which
might be another problem because it reduces the designers job to just make
things pretty).

So the best use would be for designers who code, basically unifying frontend
design and engineering.

~~~
the_gipsy
So, something like react’s storyboard would be useful to you in Elm?

~~~
deltron3030
isn't Storyboard based on components (parts) first (atomic design)?

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).

~~~
the_gipsy
You can perfectly do the design-first process with Elm, I thought you were
maybe accustomed to Storyboard or something like that.

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".

~~~
elbear
I'm don't mean to nitpick, but did you mean storybook instead of storyboard?
That's the only project that I've found which sounds like what you're talking
about

[https://github.com/storybooks/storybook](https://github.com/storybooks/storybook)

~~~
the_gipsy
Yes, totally. I must have it confused with iOS' storyboards.

------
Kiro
Completely OT but I'm curious about his use of space before exclamation and
question marks. Is it a cultural thing?

~~~
kvakil
In French, there is a space before exclamation and question marks. Based on
the author's name, I'd also guess that they are French.

------
fxfan
Anybody who liked elm is highly recommended to check out Scala.js. With
scalatags, it looks close to what elm does AND you have the entire power of
jvm libs.

And you get code sharing across client and server as its just plain old scala.
I believe elm is not big server side.

~~~
giornogiovanna
Scalatags is not a VDOM implementation, though, and the Elm architecture (one
giant state machine) is very different to what you'd typically see in a
Scala.js application. A closer analog, in my opinion, would be ClojureScript +
Reagent, but even that doesn't feature Elm's focus around immutability.

~~~
sraquo
ScalaTags is indeed not relevant here, but Scala.js has its fair share of
reactive UI libraries such as my own Laminar
[https://github.com/raquo/Laminar](https://github.com/raquo/Laminar)

~~~
lenticular
Your DOM builder library is also great for lower-level DOM manipulation.
Thanks for your work, by the way.

[https://github.com/raquo/scala-dom-builder/](https://github.com/raquo/scala-
dom-builder/)

------
anotheryou
Is anyone doing business logic with a visual tool like this one?

And if so: In production? Does it work? Do you trust non-programmers with it?

------
srean
Any HNer using Opa ? Is that alive and well. If someone has used elm and opa
would love to know about their experiences.

------
gdsdfe
hmm interesting ... on the other hand some people are trying to get away from
ELM [https://discourse.elm-lang.org/t/elm-to-bucklescript-
compile...](https://discourse.elm-lang.org/t/elm-to-bucklescript-
compiler/2871/4)

------
patsall
* Obligatory Pine joke here *

(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.)

~~~
acheron
> _Obligatory Pine joke here_

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".)

~~~
JCharante
I didn't realize there was that much of a backstory behind nano's name! Thanks
for sharing!

------
ltbarcly3
I don't understand why this is noteworthy.

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...](https://steve-
yegge.blogspot.com/2010/12/haskell-researchers-announce-discovery.html)

Functional languages are great toys but nobody uses them to get work done,
almost without exception.

~~~
yakshaving_jgt
> 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.

~~~
fsloth
That sounds really interesting! What's the market/domain of your software
product?

~~~
yakshaving_jgt
I'd say the products themselves are fairly uninteresting :)

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/](https://newbusinessmonitor.co.uk/)

[1]: [https://comparestack.com/](https://comparestack.com/)

[2]: [https://moneygains.co.uk/](https://moneygains.co.uk/)

