Check out the source code real quick. It looks very
similar to the clock example, but it is actually managing a web socket
connection! All you have to think about are the following functions:
WebSocket.send "ws://echo.websocket.org" input
WebSocket.listen "ws://echo.websocket.org" NewMessage
The first one sends messages, the second one subscribes to messages. In both
cases we provide the address of the chat server we care about and a value that
helps us communicate with it. For send
we just give it the string we want to
send. For listen
we have a tagger function, so when we receive a message
like "hi"
from the server, it is fed into our update
function as
NewMessage "hi"
.
Now the crazy thing is that we wrote a fully functional chat client without
doing a bunch of shenanigans to set everything up. We send and we listen.
That is it. I mean, it doesn't actually sound too crazy unless you know the two
options you have in JavaScript:
Use the browser API — To get started you just create a new web
socket! Well, then you need to open the connection. But do not forget to add
an onerror
listener to detect when the connection goes down and try to
reconnect with an exponential backoff strategy. And definitely do not send
messages while the connection is down, that is a runtime error! You need to
queue messages and send them later. So once you have your queue implemented,
that's it! Now you just need to decide which component owns this web socket
and make sure that the socket is closed at the appropriate time.
Use a JS library — Using the browser API seems like trouble, so
let's just find a library that does all that. Looks like we have more than
2000 options. Hmm... Hopefully
one of the first few we try works well.
In the WebSockets package for Elm, all of the babysitting of the connection
is handled automatically. The connection is opened if anyone is subscribed to
it, and it is closed if no one needs it anymore. All the queuing and
reconnecting happens behind the scenes.
Learning More
That was a super brief introduction to subscriptions. If you want to really
understand what is going on with Elm and The Elm Architecture, check out
guide.elm-lang.org. The section on The Elm Architecture slowly
builds up to subscriptions and has a bunch of nice examples.
Experienced Elm users should read the upgrade plan. You should read
guide.elm-lang.org too. I know you know Elm already, but I think the
guide really shows how all the parts of Elm 0.17 fit together in a nice way.
The sections on The Elm Architecture and ports are particularly
important for you.
And remember, you can always come talk to us on the Elm Slack channel!
We are a friendly bunch that is happy to help folks learning new stuff or
upgrading old code. Just ask!
A Farewell to FRP
Elm is about making delightful projects. Stuff like this raycaster.
Projects you are excited to share. Projects that get you excited about
programming! That means I am always asking myself how Elm can be simpler. How
can it be easier to learn? More fun? Quicker for prototyping? More reliable?
I think my obsession with these questions are the heart of Elm's design
philosophy and Elm's success.
When I started working on my thesis in 2011, I stumbled upon this
academic subfield called Functional Reactive Programming (FRP). By stripping
that approach down to its simplest form, I ended up with something way easier
to learn than similar functional languages. Signals meant piles of difficult
concepts just were not necessary in Elm.
I think anyone who has taught Elm recently would agree that signals are one of
the few stumbling blocks left. They made Elm easier than its peers, but they
did not make Elm easy.
As The Elm Architecture emerged, it became clear that you could do almost all
your Elm programming without thinking about signals at all. So the start-app
package was an experiment to see what happens when we push signals way later in
the learning path. The results were great! Folks were getting started quicker,
making it farther, and having more fun! In the end, we had lots of folks who
became excellent Elm programmers without ever really learning much about
signals. They were not necessary. Elm 0.17 is just taking the next logical step.
In the end, it was possible to remove signals because Elm has been moving
towards an explicit emphasis on concurrency for quite some time now. The seeds
for this are obvious in my thesis, but the wheels really started turning on
this in Elm 0.15 when tasks were introduced. That release also introduced a
scheduler that was able to switch between work whenever it wanted. Elm 0.17
improves this scheduler quite significantly, taking some basic insights from
the BEAM VM used by Erlang and Elixir. You can read a tiny bit about
how it works and where it is going in the Process
module
docs. This is also the foundation for effect managers, which make
subscriptions possible in the first place. I hope to flesh out the
documentation on this much more, but the nice thing is that you do not need to
know this stuff to be an Elm expert. Just like with my thesis,
Concurrent FRP, the goal is to get the benefits of concurrency for
free.
So is Elm about FRP anymore? No. Those days are over now. Elm is just a
functional language that takes concurrency very seriously. And from a user's
perspective, Elm is just a friendly functional language!
Note: Interested readers may find Lucid Synchrone interesting.
Unfortunately for me, I had no idea my thesis had so much in common with
synchronous programming languages at the time, but the connections are quite
striking. I might argue that Elm was never about FRP.
What is Next?
This release began with a vision of how Elm will handle "native" code.
What would a healthy package ecosystem look like? Elm 0.17 is the foundation
for this vision. We are now set up to support (1) everything in web platform
and (2) all sorts of custom backends like GraphQL, Elixir Phoenix, Firebase,
etc. All of these cases can be handled in terms of commands and
subscriptions, creating a consistent experience across packages that works
great with The Elm Architecture. I am excited to see this start rolling out in
the coming weeks and months!
But how to get there? Well, the web platform is
not really that much stuff when you look at it seriously, so the
@elm-lang organization will expand to cover the
remaining APIs. This is best because:
I do not expect to be compiling to JavaScript forever, especially with
WebAssembly on the horizon. The smaller the interface between Elm and JS,
the easier it will be to support other platforms.
We do not want four okay versions of bindings to web platform APIs. One
great version is better.
I know some people are eager to help with creating these libraries. Please give
me some time to develop a coherent process for making sure a desire to help can
also translate into great results. In the meantime, the best way to make
progress is to meet people on the Elm slack
and learn what is going on in the community. (You should always do that before
you start trying to make contributions!)
Thank You
First I want to thank @JustusAdam who did a
revamp of the elm-reactor
navigation pages. This contribution was made ages
ago, but it is finally out and it looks great! I also want to thank all the
folks who worked through the overall design of 0.17 with me. I know it got
crazy after a certain amount of iterations, so thanks for following along and
giving great input! Finally, I want to thank the Elm community for (1) their
patience waiting for 0.17 and (2) testing the pre-release binaries out and
finding bugs. Special thanks to @gdotdesign,
@colinmccabe, and
@lukewestby who all found sneaky issues in
the new HTML renderer and created great SSCCE's.