aboutsummaryrefslogtreecommitdiffstats
path: root/posts/elm-everything-broken.md
blob: 6e86cf67c4e43d759d3672bb9ae557139ac8f73c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
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/

<br />

<div class="sidebar">
<a href="https://www.youtube.com/watch?v=oYk8CKH7OhE">
<img src="/static/fig/elm-evan-talk.jpg" alt="photo of E.C. giving an elm talk" width="240px" />
</a>
</div>

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

<!-- If you don't know how to clone a repo, are you really going to know how to
get `cabal` set up, open a terminal and paste a command, etc? -->

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:

<pre class="terminal">
bnewbold@eschaton$ cabal --version
cabal-install version 1.20.0.3
using version 1.20.0.2 of the Cabal library 
</pre>

... so I think i'm ready to go ahead run the `BuildFromSource.hs` script:

<pre class="terminal">
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.
</pre>

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

<pre class="terminal">
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"
</pre>

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.

<div class="sidebar">
As far as I know, the only Debian packages out of the huge stable archive which
don't receive security updates are a set of web browser, mediawiki, and all
V8/node.js packages and libraries.
</div>

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

<pre class="terminal">
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.

[...]
<!--
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
-->
</pre>

<div class="sidebar">
Later I learned that I could have instead installed the nodejs-legacy
package, which just installs a symlink /usr/bin/node which points to
/usr/bin/nodejs.
</div>

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:

<pre class="terminal">
#!/bin/sh
nodejs $*
</pre>

Now I can do things like:

<pre class="terminal">
bnewbold@eschaton$ node --version
v0.10.29
</pre>

Great! Now let's install Elm with npm!

<pre class="terminal">
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
</pre>

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

<pre class="terminal">
sudo apt remove npm nodejs
rm ~/bin/node
</pre>

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:

<pre class="terminal">
sudo apt install -t jessie-backports ghc
</pre>
   
And now:

<pre class="terminal">
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
</pre>

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:

<pre class="terminal">
bnewbold@eschaton$ elm-repl 
---- elm repl 0.16.0 -----------------------------------------------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------------------------------------------------
> 
</pre>

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

<hr />

#### 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

<br />
<center style="font-size: smaller;">
<img src="/static/fig/status_haskell_broken.png" width="600px" />
<br />
Also, status.haskell.org seems to be broken again today, though
the hackage website works.
</center>

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.