This course has been updated! We now recommend you take the Introduction to Elm, v2 course.
Table of Contents
The Elm Language
Beginning Elm
Richard Feldman introduces the Elm language by comparing it to ES6. Both languages are transpiled to JavaScript. He shows a function definition and contrasts the Elm syntax with the ES6 syntax. Then he shows how to call an Elm function and how to import a module.Why bother?
Richard explores the motive for choosing to code in Elm and show some advantages—such as the Elm compiler catches errors and suggests remedies.HTML and the virtual DOM
Elm comment syntax and HTML elements are shown as functions. He answers a question on Elm vs. TypeScript.Exercise 1
The first exercise is to resolve the ToDo’s in the code provided. We’re building an application similar to GitHub but for Elm repos.Exercise 1 Solution
We add some HTML elements into the Main.elm application.Basic Data Structures
Richard talks about basic data structures in Elm such as strings, let expressions, records, tuples, and lists.Collections
Richard discusses destructuring the data structures.Exercise 2
The second exercise is to display the results of a search.Exercise 2 Solution
The search results are displayed and formatted with data destructured from the model.Booleans
The Boolean datatype and operators are shown.Partial Application
Richard explores partial function application. Partial function application means that a function can be called with fewer arguments than expected, also known as currying.List.filter and List.map
The List methods filter and map are presented.
Elm Functions
The Elm Architecture
Richard introduces the Elm architecture of model, view, and update. All of the application state lives in the model. When the update function changes the model, the view function returns the Html record and then the Elm runtime renders that as HTML.Interactivity
User interaction handlers send messages to the update function which creates a new model. That new model gets passed to view and view sends a new Html record to the Elm runtime.Exercise 3
The third exercise adds delete functionality to the search results.Exercise 3 Solution
The solution is to add a delete message to update that creates a new model by using filter.Type Annotations
Type annotations are optional but if declared the compiler will enforce them. You can create type aliases to compound type annotations.Function Annotations
Function arguments and returns can also have type annotations that are enforced by the compiler.Exercise 4
The fourth exercises involves improving documentation by adding type aliases.Exercise 4 Solution
Type annotations are added to variables, functions, and type aliases.Case Expressions
Case expressions are presented as more concise than if-then-else.Union Types
You can declare custom types. Union types can be compounds of values, constants, and functionsMessages
Messages are shown as type aliases. A case expression is used to parse the message.Exercise 5
The fifth exercise grabs a string from a text field to set the model’s query field. The second task is to add a delete by ID messageQuestions: Functions
Richard answers questions about functions without bodies. He discusses uppercase and lowercase function names.Exercise 5 Solution
Richard writes code to grab a string from a text field and add it to a message using OnInput. He uses an OnClick handler to delete a result.Questions: Functions & Messages Update
Richard answers a question about when functions are executed and the flow of messages and the Update function.
Client-Server
Result and Maybe
Built-in functions return a union type that contains two values, Ok and Err. It’s necessary to use a case expression to parse the union to get the value. The Maybe type has at most one value.Pipelines
Pipeline style allows an expression to be coded on multiple lines separated by pipes. Each line takes as it’s argument the value returned from previous line.Decoders
Decoders are functions that accept JSON data as an argument and return a value. A decoder can be composed of multiple decoders arranged pipeline style.Questions: Decoder & Refactoring
Richard explains that decoders make for easier refactoring.Exercise 6
The sixth exercise involves building a decoder for search results.Questions: Decode Identity & Naming
Richard answers questions about decode identity and function name uppercase.Exercise 6 Solution
Richard builds out the case expression that accepts the search results.Then he completes the pipe that decodes the search results.Questions: Logging, Types, Pipeline Decoding, etc
Richards answers questions about logging inside a case expression, having multiple expressions inside a case branch, uppercase for type annotations, pipeline decoding, debug.log, let expressions, and virtual DOM.Function Guarantees
Functions in Elm are pure. If you give functions the same arguments they will always return the same value. It’s impossible for Elm to have a function that generates a random number. To get a random number from Elm you must use a command.Another Function Guarantee
Elm functions do not perform side effects. Functions do not modify external state. Commands may modify external state. Tasks may also modify state.HTTP GET
Http.get takes as arguments a decoder and a URL.Exercise 7
The seventh exercise involves commands and tasks to work with the search results.Exercise 7 Solution
Richard creates a task that converts into a command that decodes the search results and handles the error.Day One Wrap Up
Richards presents some links to Elm resources and talks about his book.
JavaScript Interoperability
Questions: Imports, Subscriptions, Perf, etc
Richard answers questions about imports, graphQL, subscriptions, reordering a list, virtual DOM, performance, server-side Elm, concurrency, Elm for native mobile applications, and server-side rendering.JavaScript Interoperability
Invoking JavaScript from Elm is similar to accessing a server.The Elm Object
Commands send messages to JavaScript. Using the port keyword to talk to the DOM. The Elm object contains your ELM modules.Port
Port modules talk to JavaScript.Questions: JavaScript to Elm, Multiple Elm Apps, etc
Richard answers questions about what kind of data you can send to JavaScript from Elm, how you have multiple Elm apps on the same web page,, and how you use callbacks.Subscriptions
Subscriptions manage messages from outside Elm.Receiving Responses
Richard discusses how Elm listens for responses.Questions: Events, Handlers, Ports, etc
Richard answers questions about listening for window events and web sockets. A question is asked about click handlers and other event handlers. Ports manage communications asynchronously.Exercise 8
The eight exercise asks the user to complete the port code and implement decoders. Richard answers questions about subscriptions and ports, and getting DOM properties.Exercise 8 Solution
Richard hooks up the ports and logic for receiving the search results.Questions: Memoize JSON, Caching, Error Types
Richard answers questions about memoizing JSON requests and caching server responses. He talks about error types.The Elm Package
The elm-pack.json file is explored.
Testing
Testing Setup
The tests directory with it’s own elm-pack.json is explored, showing dependencies on test runners. Richard answers questions about npm.Testing
You can search the package manager for packages by type. Unit tests are shown in Elm and compared to Mocha and Jasmine.Fuzz Testing
Fuzz testing allows for randomly generated arguments for functions. Richards answers questions about custom fuzzers.Exercise 9
The ninth exercise asks the user to create a unit test and a fuzz test.Exercise 9 Solution
Richard completes the todos and resolves the errors revealed by the tests. He answers questions about debouncing, and task versus command.
Delegation
Elm as a Pure Function Language
Elm is compared to JavaScript as a pure function language versus an object oriented language.Delegation Introduction
Refactoring with delegation is introduced as a technique to be able to scale your application and organize your code.Building Search
The search options are scoped from the model with map functions.Exercise 10
The tenth exercise asks you to use delegation to refactor the search options in the model and the view. Richard answers questions about organizing your modules, accessing the model from the view options, and module size.Exercise 10 Solution
A new constructor function is added for the search options and the view options. Richard shows how a helper function to destructure the model may complicate your code.
Scaling Elm Code
Unidirectional Data Flow
Richard explains how to solve the deeply nested component problem with the Elm architecture.Scaling Fundamentals
Expand and refactor to scale your code. Richard answers a question about using Elm and React together, and also using multiple Elm apps, and multiple Elm app communication using ports.Scaling Examples
One way to scale the viewer the model, or update is to split into smaller helper functions.Portable Signup Form
Richard discusses approaches to creating a reusable signup form with validation.Exercise 11
Exercise 11 involves using a sortable table component.Exercise 11 Solution
The tasks to be completed are add table state to the model, initialize the state, add a new message, change the update function to receive the new message, and configure the table with the table state, and add it to the view. Richard shows another component as an example—autocomplete.Composition
Richard show various ways to write functions to access fields.
Optimization
List Performance
List performance techniques are explained by examining the underlying data structures.Array Performance
Arrays in Elm are compared to arrays in JavaScript. The dictionary data structure is introduced. A question is answered about iterating over a record.Rendering Performance
Rendering performance is improved by skipping DOM building using the lazy function.RequestAnimationFrame
Restricting the view function to repaint no faster than the browser repaints is built into Elm.Exercise 12
Exercise 12 involves using debug.log and lazy.Exercise 12 Solution
The solution adds lazy to the search results.
Tools
Tools
The first tool accepts HTML and returns Elm Html. The second tool accepts JSON and returns Elm type alias and decoders and encoders. The third tool lists compiler error messages. The fourth tool generates boilerplate Elm application code. The fifth tool is a pretty print for Elm code. The sixth tool is built into the latest version of ELM and is a history of messages that map to each change of application state. The seventh tool lets you define your CSS in Elm.Elm-css
Richard mentions the last exercise of using elm-css.Links of Interest
Links of interest.