Seven More Languages in Seven Weeks: Elm

Between the move and the election and the holidays, took me a long time to finish this chapter.

But I’m glad I did, because Elm is — dare I say — fun?

The error messages are fantastic. The syntax feels like Haskell without being as obtuse.  Even the package management system just feels nice.

A sign of how much I liked working in Elm: the examples for Day Two and Three of the book were written for Elm 0.14, using a concept called signals. Unfortunately, signals were completely removed in Elm 0.17 (!). So to get the book examples working in Elm 0.18, I had to basically rebuild them. Which meant spending a lot of time with the (admittedly great) Elm tutorial and trial-and-erroring things until they worked again.

None of which I minded because, well, Elm is a great language to work in.

Here’s the results of my efforts:

And here’s what I learned:

Day One

  • haskell-inspired
  • elm-installer: damn, that was easy
  • it’s got a repl!
  • emacs mode also
  • types come back with all the values (expression results)
  • holy sh*t: “Maybe you forgot some parentheses? Or a comma?”
  • omg: “Hint: All elements should be the same type of value so that we can iterate through the list without running into unexpected values.”
  • type inferred: don’t have to explicitly declare the type of every variable
  • polymorphism via type classes
  • single-assignment, but the repl is a little looser
  • pipe syntax for if statement in book is gone in elm 0.17
  • case statement allows pattern matching
  • case statement needs the newlines, even in the repl (use `\`)
  • can build own complex data types (but not type classes)
  • case also needs indentation to work (especially if using result for assignment in the repl)
  • records: abstract types for people without beards
  • changing records: use `=` instead of `<-`: { blackQueen | color = White }
  • records look like they’re immutable now, when they weren’t before? code altering them in day one doesn’t work
  • parens around function calls are optional
  • infers types of function parameters
  • both left and right (!) function composition <| and |>
  • got map and filter based off the List type (?)
  • no special syntax for defining a function versus a regular variable, just set a name equal to the function body (with the function args before the equal sign)
  • head::tail pattern matching in function definition no longer works; elm is now stricter about requiring you to define all the possible inputs, including the empty list
  • elm is a curried language (!)
  • no reduce: foldr or foldl
  • have to paren the infix functions to use in foldr: List.foldr (*) 1 list
  • hard exercise seems to depend on elm being looser than it is; afaict, it won’t let you pass in a list of records with differing fields (type volation), nor will it let you try to access a field that isn’t there (another type violation)

Day Two

  • section is built around signals, which were removed in Elm 0.17 (!)
  • elm has actually deliberately moved away from FRP as a paradigm
  • looks like will need to completely rewrite the sample code for each one as we go…thankfully, there’s good examples in the elm docs (whew!)
  • [check gists for rewritten code]
  • module elm-lang/keyboard isn’t imported in the elm online editor by default anymore

Day Three

  • can fix the errors from loading Collage and Element into main by using toHtml method of the Collage object
  • elm-reactor will give you a hot-updated project listening on port 8000 (so, refresh web page of localhost:8000 and get updated view of what your project looks like)
  • error messages are very descriptive, can work through upgrading a project just by following along (and refreshing alot)
  • critical to getting game working: https://ohanhi.github.io/base-for-game-elm-017.html (multiple subscriptions)

Notes from LambdaConf 2015

Haskell and Power Series Brought to Life

  • not interested in convergence
  • laziness lets you handle infinite series
  • head/tail great for describing series
  • operator overloading lets you redefine things to work on a power series (list of Nums) as well as Nums
  • multiplication complication: can’t multiply power series by a scalar, since they’re not the same type
  • could define negation as: negate = map negate
    • instead of recursively: negate(x:xs) = negate x : negate xs
  • once we define the product of two power series, we get integer powers for free, since it’s defined in terms of the product
  • by using haskell’s head-tail notation, we can clear a forest of subscripts from our proofs
  • reversion, or functional inversion, can be written as one line in haskell when you take this approach:
    • revert (0:fs) = rs where rs = 0 : 1/(fs#rs)
  • can define integral and derivative in terms of zipWith over a power series
  • once we have integrals and derivatives, we can solve differential equations
  • can use to express generating functions, which lets us do things like pascal’s triangle
  • can change the default ordering of type use for constants in haskell to get rationals out of the formulas instead of floats
    • default (Integer, Rational, Double)
  • all formulas can be found on web page: ???
    • somewhere on dartmouth’s site
  • why not make a data type? why overload lists?
    • would have needed to define Input and Ouput for the new data type
    • but: for complex numbers, algebraic extensions, would need to define your own types to keep everything straight
    • also: looks prettier this way

How to Learn Haskell in Less than 5 Years

  • Chris Allen (bitemyapp)
  • title derives from how long it took him
    • though, he says he’s not particularly smart
  • not steady progress; kept skimming off the surface like a stone
  • is this talk a waste of time?
    • not teaching haskell
    • not teaching how to teach haskell
    • not convince you to learn haskell
    • WILL talk about problems encountered as a learner
  • there is a happy ending: uses haskell in production very happily
  • eventually made it
    • mostly working through exercises and working on own projects
    • spent too much time bouncing between different resources
    • DOES NOT teach haskell like he learned it
  • been teaching haskell for two years now
    • was REALLY BAD at it
    • started teaching it because knew couldn’t bring work on board unless could train up own coworkers
  • irc channel: #haskell-beginners
  • the guide: github.com/bitemyapp/learnhaskell
  • current recommendations: cis194 (spring ’13) followed by NICTA course
  • don’t start with the NICTA course; it’ll drive you to depression
  • experienced haskellers often fetishize difficult materials that they didn’t use to learn haskell
  • happy and productive user of haskell without understanding category theory
    • has no problem understanding advanced talks
    • totally not necessary to learn in order to understand haskell
    • perhaps for work on the frontiers of haskell
  • his materials are optimized around keeping people from dropping out
  • steers them away from popular materials because most of them are the worst ways to learn
  • “happy to work with any of the authors i’ve critized to help them improve their materials”
  • people need multiple examples per concept to really get it, from multiple angles, for both good and bad ways to do things
  • doesn’t think haskell is really that difficult, but coming to it from other languages means you have to throw away most of what you already know
    • best to write haskell books for non-programmers
    • if you come to haskell from js, there’s almost nothing applicable
  • i/o and monad in haskell aren’t really related, but they’re often introduced together
  • language is still evolving; lots of the materials from 90s are good but leave out a lot of new (and useful!) things
  • how to learn: can’t just read, have to work
  • writing a book with Julie (?) @argumatronic that will teach haskell to non-programmers, should work for everyone else as well; will be very, very long (longer than Real World Haskell)
  • if onboarding new employee, would pair through tutorials for 2 weeks and then cut them loose
  • quit clojure because he and 4 other clojurians couldn’t debug a 250 line ns

Production Web App in Elm

  • app: web-based doc editor with offline capabilities: DreamWriter
  • wrote original version in GIMOJ: giant imperative mess of jquery
  • knew was in trouble when he broke paste; could no longer copy/paste text in the doc
  • in the midst of going through rewrite hell, saw the simple made easy talk by rich hickey
  • “simple is an objective notion” – rich hickey
    • measure of how intermingled the parts of a system are
  • easy is subjective, by contrast: just nearer to your current skillset
  • familiarity grows over time — but complexity is forever
  • simpler code is more maintainable
  • so how do we do this?
    • stateless functions minimize interleaving
    • dependencies are clear (so long as no side effects)
    • creates chunks of simpleness throughout the program
    • easier to keep track of what’s happening in your head
  • first rewrite: functional style in an imperative language (coffeescript)
    • fewer bugs
  • then react.js and flux came out, have a lot of the same principles, was able to use that to offload a lot of his rendering code
    • react uses virtual dom that gets passed around so you no longer touch the state of the real dom
  • got him curious: how far down the rabbit-hole could he go?
    • sometimes still got bugs due to mutated state (whether accidental on his part or from some third-party lib)
  • realized: been using discipline to do functional programming, instead of relying on invariants, which would be easier
  • over 200 languages compile to js (!)
  • how to decide?
  • deal-breakers
    • slow compiled js
    • poor interop with js libs (ex: lunar.js for notes)
    • unlikely to develop a community
  • js but less painful?
    • dart, typescript, coffeescript
    • was already using coffeescript, so not compelling
  • easily talks to js
    • elm, purescript, clojurescript
    • ruled out elm almost immediately because of rendering (!)
  • cljs
    • flourishing community
    • mutation allowed
    • trivial js interop
  • purescript
    • 100% immutability + type inference
    • js interop: just add type signature
    • functions cannot have side effects* (js interop means you can lie)
  • so, decision made: rewrite in purescript!
    • but: no react or flux equivalents in purescript (sad kitten)
  • but then: a new challenger: blazing fast html in eml (blog post)
    • react + flux style but even simpler and faster (benchmarked)
  • elm js interop: ports
    • client/server relationship, they only talk with data
    • pub/sub communication system
  • so, elm, hmm…
    • 100% immutability, type inference
    • js interop preserves immutability
    • time travelling debugger!!!
    • saves user inputs, can replay back and forth, edit the code and then replay with the same inputs, see the results
  • decision: rewrite in elm!
  • intermediate step of rewriting in functional coffeescript + react and flux was actually really helpful
    • could anticipate invariants
    • then translate those invariants over to the elm world
    • made the transition to elm easier
  • open-source: rtfledman/dreamwriter and dreamwriter-coffee on github
  • code for sidebar looks like templating language, but is actually real elm (dsl)
  • elm programs are built of signals, which are just values that change over time
  • only functions that have access to a given signal have any chance of affecting it (or messing things up)
  • so how was it?
    • SO AWESOME
    • ridiculous performance
    • since you can depend on the function always giving you the same result for the same arguments, you can CACHE ALL THE THINGS (called lazy in Elm)
    • language usability: readable error messages from the compiler (as in, paragraphs of descriptive text)
    • refactoring is THE MOST FUN THING
    • semantic versioning is guaranteed. for every package. enforced by the compiler. yes, really.
    • diff tool for comparing public api for a lib
    • no runtime exceptions EVER
  • Elm is now his favorite language
  • Elm is also the simplest (!)
  • elm-lang.org