800 karma · joined December 7, 2011
The compiler evaluates queries as much as possible at compile-time, so it is able to reduce `case` expressions, `let` expressions, etc. One neat outcome of this is that large expressions can sometimes be fully evaluated at compile-time, so they end up having no runtime cost at all!
I like this feature because it also only works because the query language is not Turing Complete. The design choices described in https://acadia.engineering/blog/solving-the-1-plus-N-query-p... that avoids 1+N patterns, also guarantees that queries terminate. This means they terminate whether you run them at runtime or at compile-time!
Anyway, the post also has an example app that uses https://github.com/acadia-engineering/elm-simple-server to run Elm code on the server, so maybe that is interesting as well.
The trick is that the same exact optimization is available in Elm and Angular 2 (with different names) so the same argument applies there as well.
The "Do these results generalize?" section makes an argument as to why the numbers you see on a simple TodoMVC app should generalize to apps of any size. When everyone has the equivalent of shouldComponentUpdate, the question becomes: when you finally DO need an update, how fast is it? That can be measured in small apps.
I also offer an analysis of "higher order" observables in https://youtu.be/DfLvDFxcAIA, and the big difference is the underlying thread architecture you get using these two.
I hope I'll be able to make these sorts of things clearer in time!
So basically, the difference is in resource management. The web socket example makes this clearer. You never have to ask "who owns the connection?" to use the connection.
I'm excited that Haskell could bring more developers to ML-family languages.
Also, thanks for taking a look at Elm! I think of it as a member of "the ML-family" of languages and I draw from a lot of lessons from working with these tools and seeing what issues have come up for other folks, both within the typed functional world and not.
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 :)
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
People searching for it online will very likely be searching for "elm union type" where they'll quickly find examples and docs. Furthermore, you can prefix the term "union type" with stuff like "closed/open" and "tagged/untagged" to start making finer grained distinctions as need higher degrees of precision. In Elm it is always tagged and closed, so in discussions within the community, adding those prefixes is redundant. Finally, if you start with the term "union type" it becomes easier to think about what an "anonymous union type" might look like (like OCaml's polymorphic variants or open variants) ;)
More broadly, if people do run into the term "union type" in other languages they will be building intuition in exactly the way I'd like: it's a way to use different types in the same place. Things happen to have this extra tag thing in Elm, but it's not so different than anything people do in JS or Clojure or Racket or TypeScript or C or whatever else. I think bringing that connection out is a major benefit of this naming choice. The goal is to feel really welcoming and friendly, and my personal preference is to build on people's existing intuition as much as possible. If someone comes from JS and does not see all the subtleties of this discussion immediately on day one, they are actually having a better experience because they can learn the info as it becomes relevant to their daily usage. Hopefully a much nicer learning curve!
I realize I am making a somewhat controversial choice, but the idea is that statically typed FP people are building artificial barriers by being sticklers about this, rather than just prefixing for precision. You may not agree with all this, but we thought it through pretty extensively, and that is the reasoning!
I also got tired of explaining "the good result goes in Right, because it's 'Right'" like I'm endlessly telling a bad dad-joke.
In the WebGL examples, I felt it made things a bit clearer since folks are probably not familiar with how WebGL works. Once you get comfortable reading types, it helps you see how things fit together, and they definitely helped me learn John's API when I was new to it :)
But if you don't need/want type annotations, you can totally take them all away and they'll be inferred! How did having them effect your experience of looking at the examples?
Conal and I definitely disagree about what is important to emphasize. FRP is a term that is used in many different ways, in the same way that FP is a term that is used in many ways. I see this as a testament to the power of the idea, and it seems like claiming that this and that are not really FRP is limiting the impact of the original work. We definitely need more precise terms though!
With the two most recent releases ( http://elm-lang.org/blog/announce/0.11.elm and http://elm-lang.org/blog/announce/0.12.elm ) it is really easy to drop an Elm component into an existing JS application, which we are experimenting with both at Prezi and in the general Elm community.
So I'd (biasedly) say to give it a try. Even if it's still too young for you, I think you'll come out of it writing way better JS :)
I'm hoping more people in the browser world come around to the idea that concurrency and parallelism aren't so tricky if you start with language design. Passing immutable objects cheaply between web workers would be a huge deal for projects like Elm!
em = 16
title = Text.height (2*em) (toText "Title")
pic = image 400 (4*em) "yogi.jpg"
I can also imagine the definition of em depending on the user's settings or fonts. In any case, we'll definitely open this up for discussion on the lists again if people start running into problems :)In the same way that JavaScript needs frameworks to have a nice high-level way to create CRUD, Elm needs libraries and frameworks too. I have been focusing on language-level details, so Elm does not have those frameworks yet. It takes time, and I'm working on it! :)
f a b <| g x y
Just like F# :)