class: middle, center
- https://guide.elm-lang.org
- https://elmprogramming.com
- https://pragmaticstudio.com/tutorials/what-is-elm
Elm is a functional programming language targeting web development.
It has an ML-like syntax
- C-like: (C, C++, Swift, Java, C#, Javascript, PHP, Perl)
- ML-like: (StandardML, Haskell, Purescript, F#, OCaml, Reason)
- Lisp-like: (Clojure, Common Lisp, Scheme)
Elm Guide: "Elm has a very strong emphasis on simplicity, ease-of-use, and quality tooling."
???
Elm is a functional reactive programming language that compiles to (client-side) JavaScript.
What does it mean to be functional?
- First Class Functions
- Immutability
- Recursion
- Expression-Oriented Programming
- Currying
- Lazy Evaluation*
- Algebraic Data Types
- Other topics (Higher Kinded Types, Existential Types)
Elm is statically typed, meaning that the compiler catches most errors immediately and provides a clear and understandable error message.
It brings the safety and stability of functional programing to front-end development.
"Elm has a very strong emphasis on simplicity, ease-of-use, and quality tooling."
Let's break that apart
- Everything you write is a pure function or a value
- Everything must have a type
- Functions are pure: they must return a type
- All values are static
- There is only one way to import functionality (vs. AMD/CommonJS/UMD)
- Fewer keywords to learn
alias, as, case, command, effect, else, exposing, if, import, in, infix, left, let, module, non, of, port, right, subscription, then, type, where
Bold words are new in ECMAScript 5 and 6.
abstract, arguments, await, boolean, break, byte, case, catch, char, class, const, continue, debugger, default, delete, do, double, else, enum, eval, export, extends, false, final, finally, float, for, function, goto, if, implements, import, in, instanceof, int, interface, let, long, native, new, null, package, private, protected, public, return, short, static, super, switch, synchronized, this, throw, throws, transient, true, try, typeof, var, void, volatile, while, with, yield
Elm-reactor is built in. It spins up a live-rebuild server with a time-traveling debugger.
The compiler just produces javascript, so integrating it is straightforward.
Programmer-friendly error messages
All elm code looks the same and it looks good.
Formatter is very fast.
Packages can only use Elm code.
This means a break from the 800k+ npm modules out there but it provides guarantees that would otherwise be impossible like:
- Tree-shaking
- Enforced semantic versioning
- Fewer security concerns (NPM Advisories)
Major: "You will have to change your software."
Minor: "There are API changes which you might want to use."
Micro: "The API hasn't changed."
???
If the API of a library changes, it will automatically get a major version bump. This solves an entire class of dependency problems.
- Syntax highlighting
- Intellisense
- Package discovery/documentation/installation)
- Jump to error
- From the Official Guide
- From a Github release page
- From npm:
npm i -g elm
- (or
npm i -D elm
for per-project install)
elm make Main.elm --output=out.js
In a realworld package.json:
"build:elm": "elm make src/elm/Main.elm --optimize --output=build/js/main_compiled.js"
In some html:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="app"></div>
</body>
<script src="out.js"></script>
<script>
const elmApp = Elm.Main.init({
node: document.getElementById('app')
})
</script>
</html>
import Elm from 'react-elm-components'
import { MyApp } from 'out.js'
function render() {
return <Elm src={MyApp} />
}
First-class currying and partial application (Chris Krycho)
var add = function add(a, b) {
return a + b
}
var add2 = function add2(c) {
return add(2, c)
}
var five = add2(3)
const add = (a, b) => a + b
const add2 = c => add(2, c)
const five = add2(3)
add a b = a + b
add2 = add 2
five = add2 3
episodeMetaData episode =
let
ordinals = formatOrdinals episode
duration = formatDuration episode.duration
in
ordinals ++ "|" ++ duration
episodeMetaData episode =
let
ordinals : String
ordinals = formatOrdinals episode
duration : String
duration = formatDuration episode.duration
in
ordinals ++ "|" ++ duration
https://learnxinyminutes.com/docs/elm/
??? paste in parts of talk_repl_yminutes.elm
Elm records vs. JS objects
difference between IF statement and IF expression
Purity
type annotations
Enums + Tagged Unions
Ports
The Elm Architecture is: Model-Update-View + Elm Runtime
Model - The current state of the app
Update - A pure function that takes the current state and a Message and returns a new state; the only place that "changes" data
View - A pure function that takes the current state and returns HTML to be rendered
Model - The definition of the data that you need
Update - Where you handle your actions
View - Where you write your divs and classes
Every Elm project you see in the wild has this, it makes orientation very easy
Debugging application logic is straightforward because there is only one place that data is "updated"
Getting started on a task is straightforward:
-
Does something look wrong? Start with the View
-
Adding a new feature? Start by adding types to the Model
-
Something not behaving correctly? Start by looking at how the Msg is handled in the update function
(Un-related: MVC vs. MVVM)
https://ohanhi.com/react-typescript-vs-elm.html
import * as React from 'react'
import * as Redux from 'redux'
// import Action and State from someplace
import * as Actions from './actions.ts'
import { State } from './reducer.ts'
interface DispatchProps {
onNameChanged: (text: string) => void
}
type Props = State & DispatchProps
const MyComponent = (props: Props) => (
<div>
<input
onInput={(event: any) => props.onNameChanged(event.target.value)}
value={props.yourName}
/>
<h1>Hello, {props.yourName}!</h1>
</div>
)
const mapStateToProps = (state: State): State => state
const mapDispatchToProps = (dispatch: Redux.Dispatch<Actions.Action>): DispatchProps => ({
onNameChanged: (text: string) => dispatch(Actions.onNameChanged(text)),
})
export default connect<State, DispatchProps>(
mapStateToProps,
mapDispatchToProps
)(MyComponent)
module View exposing (view)
import Html exposing (Html, div, text)
import Html.Attributes exposing (value)
import Html.Events exposing (onInput)
-- import Model and Msg from someplace
import Types exposing (Model, Msg(..))
view : Model -> Html Msg
view model =
div []
[ input [ onInput NameChanged, value model.yourName ] []
, h1 [] [ text model.yourName ]
]
- NoRedInk/elm-json-decode-pipeline
- danyx23/elm-uuid
- elm/time
- elm-community/list-extra
- elm-community/string-extra
- mhoare/elm-stack
- wernerdegroot/listzipper
???
Ask people what looks interesting
Look at String-Extra
Remember that all libraries are 100% Elm
You can Google and/or Youtube for:
awesome-Elm, Elm weekly, Elm courses, Elm books, Elm slack, Elm subreddit, Elm stackoverflow
Realworld project implementation by Richard Feldman: https://github.com/rtfeldman/Elm-spa-example
https://github.com/isRuslan/awesome-Elm
Why We Still Choose (and Recommend) Elm in 2019?
Github list: https://github.com/jah2488/Elm-companies
More well-known companies:
- Microsoft (https://github.com/Microsoft/Elm-json-tree-view)
- IBM (https://discourse.Elm-lang.org/t/ibm-releases-Elm-powered-app/2364)
- Ableton (makers of Ableton Live) (https://learningmusic.ableton.com/)
- Adobe
Midwest.io 2014 - Demystifying Haskell - Andrew Rademacher
Evan Czaplicki - Convergent Evolution
"Making Impossible States Impossible" by Richard Feldman
Elm Europe 2017 - Evan Czaplicki - The life of a file
(un-ordered, un-tested, some paid)
- https://pragmaticstudio.com/Elm
- https://www.pluralsight.com/courses/Elm
- https://frontendmasters.com/courses/intro-Elm/
- https://egghead.io/browse/languages/Elm
- https://courses.knowthen.com/p/Elm-for-beginners
- https://www.lynda.com/Elm-tutorials/771008-0.html