This is a recounting of my journey to determine if the Elm programming language would live up to its promise and potentially become my tool of choice for web browser-based front end development. My journey started long before this recounting. I have more than 30 years of experience with software development, some limited experience with functional programming, but I have never used Elm in any capacity. After fighting the HTML5/CSS/JavaScript battle yet again I began this analysis of alternatives. I was looking for a better way and Elm looked promising.
Any exploration into a new language begins with preparing the development environment.
For Elm, there are installers available for Windows and Mac and a binary for Linux, but since elm-format and elm-test are installed via Node Package Manager, I installed Elm with npm also. (If you don't already have Node.js and NPM, you will need install them before running the commands below. I recommend using Chocolatey on Windows or your package manager on Linux to install Node.js and NPM.)
First, install the Elm platform.
npm install -g elm
Add support for automatically formatting your code.
npm install -g elm-format
Add code completion and documentation lookup.
npm install -g elm-oracle
npm install -g @elm-tooling/elm-language-server elm-analyse
And finally, add the ability to run unit tests.
npm install -g elm-test
For Fedora Linux, you may need to follow the instructions below (based on the instructions here) to resolve the permissions issues for installing globally. You can perform this procedure on any Linux distribution and MacOS, but it does not apply to Windows outside of WSL. During testing, I successfully completed the following procedure on Fedora 32, Manjaro 20.0.3, NixOS 2.3.7 and Ubuntu 20.04 (both stand alone and under the Windows Subsystem for Linux).
If you do not need your global packages to be available to other users or processes, you may want remove the existing packages before relocating your global local repository. You can remove the global packages automatically from within your shell with the following.
npm remove -g $(npm list -g --depth 0 | rg [├└]── | awk '{ print $2 }' | sed -E 's/^(@?.*?)@.*/\1/' -)
If you need to pick and choose which global packages to remove, you can list the currently installed global packages with the following.
sudo npm list -g --depth 0
And then remove each manually with the following.
sudo npm remove -g <package name>
Create and initialize a directory for global installations.
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
Add the following to ~/.bash_profile
, ~/.bashrc
, ~/.profile
, ~/.zshrc
, or ~/.zshenv
as appropriate for your shell of choice.
export NPM_CONFIG_PREFIX=~/.npm-global
export PATH=$PATH:~/.npm-global/bin
Source the file, as appropriate to your distribution, to get the updated environment variables.
source ~/.bash_profile
# or
source ~/.bashrc
# or
source ~/.profile
# or
source ~/.zshrc
# or
source ~/.zshenv
This should resolve the permissions errors so that you can successfully install the packages as shown [above](#Install the Compiler and Tools).
Your editor is one of the most important components in the tool chain since it is where you spend most of your time. I looked at each of the editors listed in An Introduction to Elm to determine how well they support capabilities such as syntax highlighting, formatting, diagnostics, completions, etc. In general, the editors use elm-oracle to support Elm versions prior to 0.19 and @elm-tooling/elm-language-server for versions 0.19 and later. Some support both. Elm 0.19 introduced major changes to the terminal commands, a new standard library, a redesigned package system, and more. Apparently, these changes were so extensive that many projects didn't transition to 0.19. Since I am new to Elm, I will only be looking at 0.19 support and the following are just my impressions of how well an editor currently supports development in Elm version 0.19.
For Atom, you can't go wrong with elmjutsu for Elm 0.19 and later. If you follow the directions provided by the elmjutsu package with the atom-ide-ui optional recommendations, you'll have an excellent Elm development environment.
Brackets with elm-brackets
I can't recommend Brackets for Elm development because if supports only versions of Elm prior to 0.19 and there doesn't seem to have been any recent updates on the plugin. If you're using Brackets and developing for an older version of Elm, it might be an option for you.
Joseph Collard's excellent elm-mode package supports all Elm versions and provides an excellent Elm development experience. If you like to tune every detail of your development environment, this is the editor for you. It can be challenging to configure if you start from out-of-the-box Emacs. I recommend a Vim/Emacs hybrid configuration like Doom Emacs or Spacemacs as a good starting point, but if you're a roll your own configuration fan, you might want to look at Steve Purcell's Emacs configuration bundle for ideas on how to configure Emacs for Elm. Definitely one of the better solutions in this list but also more challenging to setup.
Below are a few notes that might be useful to you in setting up your Elm environment in Doom Emacs.
- In your
~/.doom.d/init.el
(Space f P from Doom Emacs), definitely enablecompany
,lsp
andelm
and use(elm +lsp)
to tellelm-mode
to use the language server protocol. Also enablespell
,javascript
,web
, andyaml
for front end development. - In your
~/.doom.d/config.el
, add(add-to-list 'company-backends 'elm-company)
to the end of the file.
Also, if you are running Windows and have trouble getting spell checking to work correctly, the following may be helpful: ispell/hunspell/Windows: a fully-worked example.
JetBrains IntelliJ IDEA or JetBrains WebStorm with the Elm plugin
Easy to setup; just install the plugin. The JetBrains Elm plugin provides an exceptional development experience for the Elm developer. If you're already using IntelliJ IDEA or WebStorm, you won't be disappointed with the Elm support. Compared to the other editors in this list, I found the JetBrains editors to be significantly slower to startup (due to their JVM heritage), but responsive and very easy to use once they were up. Definitely one of the better solutions in this list.
LightTable with elm-light
I was not able to use the Linux binary provided on LightTable.com nor build a Linux binary that would run successfully on any recent version of Linux (Fedora 32, Manjaro 20.0.3, NixOS 2.3.7 or Ubuntu 20.04).
I was able to install LightTable and the elm-light plugin on Windows 10, but even after after following the Elm Light Guide to configure the elm-light plugin on Windows 10, I was not able to use it because the elm-light plugin supports only versions of Elm prior to 0.19.
At this time, I cannot recommend LightTable for Elm 0.19 development.
LSP, LSP-elm, Elm Syntax Highlighting, and Elm Format on Save combine to form a very effective development environment for Elm. The resulting environment feels lightweight and responsive and it provides the user with just the right amount of feedback without being distracting.
Like Emacs, Vim/NeoVim provides the development experience using the elm-language-server. Follow the instructions provided on the elm-language-server page to configure Conquer of Completion and use the example .vimrc as a good starting point for your configuration. Also like Emacs, setting up Vim/NeoVim for Elm development is more challenging than form most of the other editors in this list, but the end result is very responsive and very satisfying to work in.
Visual Studio Code with Elm
Beginning users will love VSCode with Elm. It is exceptionally easy to setup (install the Elm plugin and go) and provides all of the features you would expect from a full-featured editor. Definitely one of the better solutions in this list and my recommendation for beginners or for anyone who what's to get started with minimal fuss.
One of the biggest factors that led to my giving Elm a try was the quality of the compiler's error messages. After reading what I assumed to be a lot of hype related to error messages. I decided to put it to the test.
- elm init
- empty src/Main.elm
- compile and show results
- use elm-format and show results
- compile and show results
- walk through getting some output
npm install -g elm-upgrade