7 ms·
The Elm Architecture
- saosebastiao 12y agoSo out of all the compile-to-javascript languages out there, elm is easily my favorite, despite not being usable outside the browser. This article is one illustration why it is so attractive: app architecture that is blindingly simple (its all just state machines under the cover, which is exactly what a UI is). 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?
- wz1000 12y agoHaskell with an FRP library may work for what you want to do. Reactive-banana looks good, though I haven't used it.
- phamilton 12y agoI'll echo this. Elm was a bit of a gateway drug for me getting into Haskell. Haskell itself has a lot of very powerful tools.
- platz 12y agoThis post builds the intuition for something like the Netwire library http://blog.jle.im/entry/effectful-recursive-real-world-autos-intro-to-machine http://blog.jle.im/entry/effectful-recursive-real-world-auto...
- photex 12y agoThe trouble though comes about once you have to start working with a UI library. It's a mess and a half unless you use C++. I'd like to try using Elm, or Purescript for UI work using atom-shell or nw.js. That opens almost the same can of worms (how easy it might be to 'bind' your engine to your UI/view). I've written a non-trivial application using QtWebkit entirely for the UI and it was a very agreeable experience. The engine of this app was C++ but it got my gears turning.
- pjmlp 12y agoActually that I my opinion from any web based UI, a mess of JavaScript/CSS trickery and HTML. Native UI development feels so much more advanced and user friendly. Saying this as a UX developer since the mid-90's.
- photex 12y agoMy comment was in reference to using native toolkits from a language other than C++ and not the status of using native toolkits in general. <friendly-joke>I have a hard time believing that you've been using native UI toolkits using Haskell since the mid-90s.</friendly-joke> :)
- pjmlp 12y agoNo, but I was using Turbo Pascal followed by Delphi. Also played with C++ Builder, but by then Visual C++ had taken over as Borland was going through their Inprise phase.
- Rapzid 12y agoI haven't tried Elm yet but my favourite thus far is ClojureScript. Last I used it the workflow had a few rough edges but once I discovered you didn't HAVE to create closure(the google closure stuff) mappings it became easier to get the feet wet. I should take Elm for a drive.
- sonnym 12y agoI, too, really love Elm, and have worked on some tooling for getting it running on the server. (Self promotion ahead). I wrote an NPM module for compiling and loading Elm[1], and also put together a more comprehensive project for scaffolding an Express application to communicate between Elm in the browser and Elm on the server, via ports (this is the first time I announce it anywhere, since I want to have some full examples before anything "official", but it is usable today). 1. https://www.npmjs.com/package/elm-loader https://www.npmjs.com/package/elm-loader 2. https://www.npmjs.com/package/elm-expressway https://www.npmjs.com/package/elm-expressway
- tegeek 12y agoInteresting. So basically Reactive Haskell right inside the NodeJS. Did you able to run any performance test yet? I'm interested to learn more about this.
- sonnym 12y agoIt performs perfectly fine on my machine, but I have not done any comprehensive testing. I was actually quite surprised when I first got everything working and was streaming input to the server, state to the client, and rendering the latter without any obvious latency. There are even some trivial optimizations, such as dropping repeats from the state signal on the server, which should speed things up significantly. I have no idea if it will scale, but I do plan on adding some infrastructure for writing bots in Elm and having them run in a cluster, so it should be easy enough to test at some point. This is a working example of the Pong example from the Elm website: https://github.com/sonnym/elm-expressway_pong https://github.com/sonnym/elm-expressway_pong
- atrilumen 12y agoIt's killing me that there isn't a good enough solution to this right now. 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.) [0] http://idris-lang.org http://idris-lang.org [1] http://frege-lang.org http://frege-lang.org (appears to be down ATM) [2] http://www.robovm.com http://www.robovm.com [3] http://www.gwtproject.org http://www.gwtproject.org
- voxfrege 12y agoIt is http://www.frege-lang.org http://www.frege-lang.org or simply https://github.com/Frege/frege https://github.com/Frege/frege
- cogware 12y agoMy experience with Elm was that it's very elegant and fun to work with if you are building a purely clientside application, but once you need communication with server the APIs are not very well developed and it becomes a major headache. Note that none of the examples in this page (or in any Elm tutorial I found) flesh out interaction with a backend.
- phamilton 12y agoConsuming data isn't hard. Creating a dashboard that displays the values sent down on an interval over a websocket is super easy. 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.
- cogware 12y agoYep, it was specifically when I wanted an application that would run a game loop involving round trips to the backend for every step that I ran into a lot of difficulty. Ports were not very clearly documented and I didn't find any examples, so I wound up writing Javascript instead.
- cogware 12y agoYep, it was specifically when I wanted an application that would run a game loop involving round trips to the backend for every step that I ran into a lot of difficulty. Ports were not very clearly documented and I didn't find any examples, so I wound up writing Javascript instead.
- CGamesPlay 12y agoI ended up implementing this in JavaScript using Rx, but the core concept is the same: Incoming requests: --a-------------> Requests to server: ---b------------> Responses from server: -----------d----> Updates to app state: ---c--------e---> a - User "sends message" to chat room b - 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
- gilgoomesh 12y agoA little off topic but I followed the links to elm-lang.org and the examples page is filled with unlicensed copyright/trademark material (images and trade-dress from Super Mario World, Legend of Zelda and Apple's iOS Calculator): http://elm-lang.org/Examples.elm http://elm-lang.org/Examples.elm A bit disappointing.
- amelius 12y agoIt all looks great, but I wonder what happens when my model is actually a large database (or, for example, a large map), and the visual components are each observing changes in this database (or map). Would the database be one big signal? Or would the database be a large collection of signals? How would one model this (efficiently) in elm?
- amelius 12y agoI wonder if it is also possible in elm to perform layout-dependent logic. For example: show a piece of text horizontally, but if it is too wide (in pixels), show it vertically.
- PaulHoule 12y agoWow, that looks like COBOL.
- jacquesm 12y agoI've programmed COBOL for a living back when it was still fashionable and I don't think it looks like COBOL at all, what specifically triggers your 'looks like' bit?
- PaulHoule 12y agoThe separate sections for data definitions, forms, etc.
- jacquesm 12y agoAh, the 'divisions'. Right, I see what you mean. Quite a few languages have such 'divisions', though they're not usually explicit. For instance, C code usually has a bunch of include statements at the top, followed by internal structure declarations followed by function definitions. 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.
- mod3rn0 12y agoThose are just simple examples. If the code grows you can always split up the sections into different modules.
- jasim 12y agoI've been thinking of giving Elm a go, and this walk-through is very helpful in breaking the initial barrier. Exciting to see these ideas finally giving us answers on how to do user interfaces on the web right. 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?
- Lethalman 12y agoWhen there was no React.js, I had in mind something like that and implemented a very simple concept like this with ghcjs. Functional languages tend to let you write this kind of code. 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.
- jasim 12y agoThanks a lot for the response. Your comment about constraints improving design makes a lot of sense. 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.
- Matthias247 12y agoI have read the document and find the ideas around Elm really interesting. It seems nicely designed and is also understandable for a newcomer in FP. 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.