Title: Everything Is Broken (Installing Elm Edition) Author: bnewbold Date: 2016-05-06 Status: draft *This post is a narrative rant (in the same vein of Dan Luu's ["Everything is Broken"][danluu] post) about my problems one afternoon getting a Fancy New Programming Language to work on my laptop. Skip to the end for my thoughts on a solution.* [danluu]: https://danluu.com/everything-is-broken/
A few folks here at the [Recurse Center][rc] had nice things to say about the [Elm programming language][rc], and after watching Evan Czaplicki's ["Let's Be Mainstream" talk][0] I got pretty excited also. Let's try Elm! [rc]: https://recurse.com/ [elm]: https://elm-lang.org [0]: https://www.youtube.com/watch?v=oYk8CKH7OhE First I go in the front door with the [install page][install], which redirects me to a page which instructs me to use npm. [install]: http://elm-lang.org/install Hrm, I've had painful experiences with npm in the past, and anyways, isn't the Elm compiler implemented in Haskell? Why are they using a package management tool for Javascript libraries for installation? No thanks, I'll [build from source][build], following these directions from the `README.md`: [build]: https://github.com/elm-lang/elm-platform # If you are on LINUX, you need to install a dependency of elm-repl. # Uncomment the following line and run it. # sudo apt-get install libtinfo-dev # if you are on windows, or some other place without curl, just download this file manually curl https://raw.githubusercontent.com/elm-lang/elm-platform/master/installers/BuildFromSource.hs > BuildFromSource.hs runhaskell BuildFromSource.hs 0.16 Weird that these build-from-source directions involve curl-to-file magics. Why not just clone the repo and use a Makefile, which is roughly the same number of commands to enter? I clone repo and run the script from there instead. I'm on Debian stable ("jessie"), so installing GHC (the most popular way to use Haskell) is easy. I seem to have a recent version of cabal:
bnewbold@eschaton$ cabal --version
cabal-install version 1.20.0.3
using version 1.20.0.2 of the Cabal library 
... so I think i'm ready to go ahead run the `BuildFromSource.hs` script:
bnewbold@eschaton$ runhaskell ~/src/elm-platform/installers/BuildFromSource.hs 0.16

GHCi runtime linker: fatal error: I found a duplicate definition for symbol
_hs_bytestring_long_long_uint_hex
whilst processing object file
/home/bnewbold/.cabal/lib/x86_64-linux-ghc-7.6.3/bytestring-0.10.6.0/HSbytestring-0.10.6.0.o
This could be caused by:
* Loading two different object files which export the same symbol
* Specifying the same object file twice on the GHCi command line
* An incorrect `package.conf' entry, causing some object to be
    loaded twice.
GHCi cannot safely continue in this situation.  Exiting now.  Sorry.
Uh-oh! Not sure what that means. A search returns [a FAQ entry][faq-entry] about "Duplicate Directions". It doesn't seem like *I* have done anything wrong. I'll update `cabal`'s package index: [faq-entry]: https://wiki.haskell.org/GHC/FAQ#Duplicate_Definitions
bnewbold@eschaton$ cabal update
Downloading the latest package list from hackage.haskell.org
cabal: Failed to download
http://hackage.haskell.org/packages/archive/00-index.tar.gz : ErrorMisc "Error
HTTP code: 502"
At first I assumed I was doing something wrong, or maybe the WiFi was flakey, but it turns out that the Hackage package repository [is down](https://status.haskell.org/): > hackage.haskell.org down > > Full Service Disruption > > [Investigating] The hackage server is in an out of memory condition. We're investigating. Well, wasn't even sure if updating my package index would fix the problem. I'll give up and try npm, which these days has been [sort of packaged][deb-node] in Debian. I'll just uninstall npm when I'm done installing Elm. I install with `apt` (which pulls in a huge list of `nodejs` packages), but then can finally run: [deb-node]: https://www.debian.org/releases/stable/amd64/release-notes/ch-information.en.html#libv8
bnewbold@eschaton$ npm install elm
|
> elm@0.16.0 install /home/bnewbold/bin/node_modules/elm
> node install.js

sh: 1: node: not found
npm WARN This failure might be due to the use of legacy binary "node"
npm WARN For further explanations, please read
/usr/share/doc/nodejs/README.Debian

npm ERR! elm@0.16.0 install: `node install.js`
npm ERR! Exit status 127
npm ERR! 
npm ERR! Failed at the elm@0.16.0 install script.
npm ERR! This is most likely a problem with the elm package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node install.js
npm ERR! You can get their info via:
npm ERR!     npm owner ls elm
npm ERR! There is likely additional logging output above.

[...]

Looks like Debian wants to call node.js `nodejs` while npm/Elm expects it to be called `node`. Ok, I create this shim named `node` in my `~/bin` directory (which is on my `$PATH`), and make it executable:
#!/bin/sh
nodejs $*
Now I can do things like:
bnewbold@eschaton$ node --version
v0.10.29
Great! Now let's install Elm with npm!
bnewbold@eschaton$ npm install elm

> elm@0.16.0 install /home/bnewbold/bin/node_modules/elm
> node install.js

Downloading Elm Reactor assets from https://dl.bintray.com/elmlang/elm-platform/0.16.0/elm-reactor-assets.tar.gz
Error communicating with URL https://dl.bintray.com/elmlang/elm-platform/0.16.0/linux-x64.tar.gz Error: CERT_UNTRUSTED
npm WARN This failure might be due to the use of legacy binary "node"
npm WARN For further explanations, please read
/usr/share/doc/nodejs/README.Debian

npm ERR! elm@0.16.0 install: `node install.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the elm@0.16.0 install script.
npm ERR! This is most likely a problem with the elm package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node install.js
npm ERR! You can get their info via:
npm ERR!     npm owner ls elm
npm ERR! There is likely additional logging output above.

npm ERR! System Linux 3.16.0-4-amd64
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install" "elm"
npm ERR! cwd /home/bnewbold/bin
npm ERR! node -v v0.10.29
npm ERR! npm -v 1.4.21
npm ERR! code ELIFECYCLE
npm ERR! 
npm ERR! Additional logging details can be found in:
npm ERR!     /home/bnewbold/bin/npm-debug.log
npm ERR! not ok code 0
Whoops. There is [a github issue][elm-issue] that has some tips about this: the recommended solutions online are basically "upgrade node.js and npm" or "disable SSL security". That doesn't sound great, but i'm feeling very impatient at this point so I tried disabling SSL checks with npm config set ca null`, but even then I get the same certificate error. Enough of that approach: [elm-issue]: https://github.com/elm-lang/elm-platform/issues/100
sudo apt remove npm nodejs
rm ~/bin/node
Poking around a bit more, I find the promisingly-titled "`fubar.sh`" script in the `elm-platform` repo cloned earlier, which seems to nuke the local user's Haskell (`cabal`) stuff (but doesn't muck with system-wide package, eg `apt` managed GHC libraries). After running `fubar.sh` the `BuildFromSource.hs` script seems to start working, though Hackage is still down (now, an hour after I started this process, approaching 5 hours total downtime), so I can't install dependencies. I search for a hackage mirror and find that [FPComplete runs one](https://www.fpcomplete.com/blog/2015/03/hackage-mirror). In addition to their directions I had to set `remote-repo-cache` in my `~/.cabal/config`, like so: remote-repo: hackage.fpcomplete.com:http://hackage.fpcomplete.com/ remote-repo-cache: /home/bnewbold/.cabal/packages-fpcomplete After that I `cabal update` and run the `BuildFromSource.hs` script again. It fails to build the dependency `websockets-snap`, but I try installing that regularly (`cabal install websockets-snap`) and that works, then all the dependencies with BuildFromSource.hs build. Yay! I still get an error with compiling Elm itself though: src/Elm/Package.hs:60:25: Not in scope: `<$>' Perhaps you meant `' (imported from System.FilePath) It [sounds like](https://github.com/elm-lang/elm-platform/issues/30) I am using an out of date version of GHC (the Haskell compiler): I have 7.6.3 (the version that comes with Debian), and Elm wants 7.10. Fair enough: unlike a package manager, I can see how new features in the compiler would be helpful, and when I go back and look this is in the README. Fortunately there is a new version of GHC in the `jessie-backports` repo, so:
sudo apt install -t jessie-backports ghc
And now:
bnewbold@eschaton$ cabal --version
cabal-install version 1.22.6.0
using version 1.22.5.0 of the Cabal library 
bnewbold@eschaton$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.10.3
After that, I'm miraculously able to compile. Horray! I add `~/bin/Elm-Platform/0.16/.cabal-sandbox/bin` to my `$PATH` and I can run:
bnewbold@eschaton$ elm-repl 
---- elm repl 0.16.0 -----------------------------------------------------------
:help for help, :exit to exit, more at 
--------------------------------------------------------------------------------
> 
Success! Throughout this debugging experience I had problems with both my external [Lenovo Thinkpad USB keyboard][keyboard] glitching (workaround: unplug and re-plug) and with WiFi at the Recurse Center disconnecting (workaround: reset wifi card). Others here using GNU/Linux have the same wifi problems, but we don't have a fix yet... something to do with wireless regulatory zones. It's not all pain though; installing the `elm.vim` syntax highlighting plugin was very easy, just a single `git clone` into `~/.vim/bundle/`. [keyboard]: https://www.amazon.com/Lenovo-ThinkPad-Compact-Keyboard-TrackPoint/dp/B00F3U4TQS So Now What? ---------------- TODO: dan's auto-testing tips There was a great long-form blog post by Same Boyer a few months ago (["So You Want To Write a Package Manager"][5]) which discussed Rust's package manager, Cargo. [Yehuda Katz and Carl Lerche][6] designed Cargo. Ironically, given the difficulty I had installing it, the Elm language's package manager has a great `diff` tool for checking that any changes in the API conform the [documented][8] [semantic versioning][semver] conventions. For [example](https://gist.github.com/badboy/a302dd0c9020e5759240): $ elm-package diff evancz/elm-html 3.0.0 4.0.2 Comparing evancz/elm-html 3.0.0 to 4.0.2... This is a MAJOR change. ------ Changes to module Html.Attributes - MAJOR ------ Removed: boolProperty : String -> Bool -> Attribute stringProperty : String -> String -> Attribute ------ Changes to module Html.Events - MINOR ------ Added: type alias Options = { stopPropagation : Bool, preventDefault : Bool } defaultOptions : Html.Events.Options onWithOptions : String -> Html.Events.Options -> Json.Decode.Decoder a -> (a -> Signal.Message) -> Html.Attribute This change information is then used to *[programatically enforce][7]* the versioning rules and prevent a whole class of simple but annoying breakages due to API change. [5]: https://medium.com/@sdboyer/so-you-want-to-write-a-package-manager-4ae9c17d9527 [6]: https://mail.mozilla.org/pipermail/rust-dev/2014-March/009090.html [7]: https://github.com/elm-lang/elm-package/blob/master/README.md#version-rules [8]: https://github.com/elm-lang/elm-package/blob/master/README.md#publishing-updates [semver]: http://semver.org/ [appcheck]: http://www.linuxfoundation.org/collaborate/workgroups/lsb/linux-application-checker-getting-started
#### Follow up June 18th, 2016 A few days after writing this post, a new version of Elm (0.17) was [released](http://elm-lang.org/blog/farewell-to-frp). The new version made some big changes, like abandoning the [Functional Reactive Programming][frp] paradigm. I found that many of the new tutorials weren't working with my 0.16 install, so I tried to upgrade. After an hour or two of following the directions above, I gave up and installed npm on a temporary Debian unstable ("sid") virtual machine. Once I added a `node` symlink to `nodejs`, I was able to install `elm` with npm and develop remotely using `screen` and `elm-react`. Frustrating! [frp]: https://en.wikipedia.org/wiki/Functional_reactive_programming

Also, status.haskell.org seems to be broken again today, though the hackage website works.
On the plus side, my USB keyboard problem seems to have been due to the cheap random USB cable I was using. Since replacing it I haven't had the bad flakey-ness, though now after my laptop awakes from sleep the pointer and keyboard work but the middle mouse button ("paste" on UNIX) does not. Workaround: plug and unplug the whole keyboard.