The Elm Architecture
github.com
github.com
Now all we need is an elm that compiles to native code that somehow can do what React Native is doing for the native interface. I would easily pay 3-5x Xamarin's prices to be able to do so. Who's up for it?
http://blog.jle.im/entry/effectful-recursive-real-world-auto...
Native UI development feels so much more advanced and user friendly.
Saying this as a UX developer since the mid-90's.
I should take Elm for a drive.
Did you able to run any performance test yet? I'm interested to learn more about this.
This is a working example of the Pong example from the Elm website: https://github.com/sonnym/elm-expressway_pong
Some quick notes:
[0] Idris compiles to C, Java, and JavaScript, but is considered experimental.
[1] Frege compiles to Java, and seems to have fairly nice Java interop. It may be possible to target iOS via RoboVM [2], and the browser via GWT [3].
I've yet to really dig into either of them yet, so I can't claim any level of confidence.
My current best hope is that GHC's ARM support will become mature enough someday before Sol goes supernova. (Or at least before the effective heat-death of the universe.)
(I'm still learning Haskell and kin, so I can't be of much help yet.)
[1] http://frege-lang.org (appears to be down ATM)
ReactJS has also converged into the ideas proposed by Elm: the Model is explicitly defined (props and state); view is always a function of the Model; and the Model is mutated only through Signals (one-way bound callbacks in plain React, Actions when using Flux).
I have a question for anyone who've worked with both Elm and React. It seems to me that these ideas (component model, well-defined mutation point for state, composability, one-way binding etc.) are what matters more than the language itself. Granted that the language can influence how code is written (immutability, pure functions, ..), but does Elm (or ClojureScript for that matter), drastically improve creation of typical user interfaces just by virtue of the language?
It felt very organized and just worked, then I looked at Elm and said: "that's exactly what I thought I'd do with ghcjs". Then with react.js: "finally somebody implemented the concept in plain javascript". Which is after all a kind of stricter mvc model for the single-page web applications. The fact is that with an haskell-like language, the kind of mvc concept is much more structured, you do less design mistakes because the language itself constraints the effects. So what react.js did is adding these constraints on top of plain js in an elegant way.
In other words: I think the addition of elm is the language itself, for those acquainted with haskell and where type checking matters a lot, compared to plain js.
On the same path, there are other libs similar to react.js that are even faster because they have stricter requirements on how data is mutated.
As to libs similar to React, I assume you're talking about Mercury and Mithrill. But I'm quite happy with React's performance and escape latches (shouldComponentUpdate). I'll however switch in a heartbeat if a better design comes along.
The problem is that unlike when I was mutating DOM with spaghetti JS or wrangling with Angular, I am yet to say "why is this thing so darn difficult" with React for almost all use cases I've thrown at it (yet to figure out animations). And the last React.js Conf has taken care of most things that I could imagine improving in web development with Relay and CSS in JS.
1. How much is the language going to help you independently arrive at nice architecture? It took millions of people 20 years to arrive at this pattern in JS, and it literally happens in every Elm program out there automatically. The pattern described in "The Elm Architecture" really does come from looking at people's Elm code and seeing the naturally arising patterns. So new people don't need to read this post and learn these concepts, commercial users don't need to have strict discipline, the architecture just comes out this way.
2. How much is the language going to fight you or help you when you already know what you want to do? In particular, ADTs are a key part of why this is so nice in Elm, and when you are working in JS or TypeScript, writing "the same code" leads to code that can be quite awful. Even when you know why you want it, it often does not seem worthwhile to fake ADTs. Immutability is another key aspect that's hard to get in many languages. I'll write more about this in some future post, but I think lack of side-effects is another key aspect of keeping the architecture nice.
3. How much is a language going to help a team of 20 keep this up in a large code base? Will the intern or the new hire be able to do it right? Once you start to get cracks, do they continue to grow? If you lack a module system or a type system, are you going to start running into other scaling problems? In this setting, having tools that guide you to the right answer is extremely valuable.
So I think language matters a lot, but I would :P
I appreciate the practical lens with which you've described how the language can influence code. Many language geeks far too often remain too abstract about how a craftsman programmer's life can be improved by the language's design.
ADTs stood out as something I'd love to have in my day-to-do programming toolbet during my short tryst with Haskell. But I was unable to articulate the concrete improvements it can bring into my code, and so it has unfortunately remained a hunch. I eagerly look forward to your post about ADT in the context of Elm and UI programming.
Note that none of the examples in this page (or in any Elm tutorial I found) flesh out interaction with a backend.
Sending data isn't hard. Sending the mouse coordinates on a click to the server over a websocket is super easy.
There is, however, no easy way to consume data and send a response. To write an echo server, for example, you currently have to send the data to a javascript port and then read from the port to send it back.
Incoming requests: --a------------->
Requests to server: ---b------------>
Responses from server: -----------d---->
Updates to app state: ---c--------e--->
a - User "sends message" to chat roomb - Handler for that action queues a request
c - Handler for that action also queues a local update
d - Server responds with the sent message
e - Handler for that response queues a local update
That said, I've release a client/server game (online sailing regattas) in Elm & Play/Scala with websockets, and current API was enough for me: https://github.com/etaque/tacks
The TodoMVC example in Elm does this to use localStorage: https://github.com/evancz/elm-todomvc/blob/master/Todo.elm#L... and https://github.com/evancz/elm-todomvc/blob/master/index.html...
The same can be done for HTTP or WebSockets if you have needs that are not met by the existing APIs. Furthermore, the next major release is focused on drastically improving these APIs.
So there's a safety valve right now and there's a plan of how to make things excellent. I would not block on this, but I am also relatively biased :)
Some things that would interest me but which I couldn't figure out from these docs are:
1. Will sending something to a Channel or the DOM event that causes the send to the channel (e.g. onClick (send channel Decrement) in the example) be executed synchronously (aka direct function calls in the transpiled JS) or asynchronously (signal processing in the subscriber is deferred, e.g. with settimeout). If it's deferred, can it really be guaranteed that for example a button could only be pressed once (with direct calls you could disable it immediatly in the onClick listener) or other actions which you might want to see immediatly?
2. Are there any concepts around cancellation? E.g. in one other example there was a textbox whose text-changed signal triggered the downloading of images which were shown in another view. There old pictures were still shown despite the input has changed already again because they are in the HTTP response signal at some point of time. I guess you would have to create and map a new HTTP signal each time the input change and disconnect the old one. But this seems like against the proposed architecture.
http://elm-lang.org/Examples.elm
A bit disappointing.
We don't name the sections there but they might as well have names (you can include a file in the middle of another but that's pretty bad form). Other languages are more formal (for instance Modula-2, Erlang, Ada). That's not a COBOL specific thing.