elm-talk



elm-talk

0 0


elm-talk

Slide and examples from my Full Stack San Diego talk on 11/12/15

On Github thunklife / elm-talk

Elm

Typed Functional Programming For The Web
  • Elm is a language looking to compete to be the next language for the web
  • It's goal is to bring more maintainable development to JavaScript, while being approachable

Why Choose Elm?

  • Of course there are plenty of of options for comile to JS langs
  • So why choose Elm

Purity

x → y
  • Functions operate on inputs only, and have no side effects
  • Functions are referentially transparent, they always return the same output for a given input
  • Effects in Elm are Managed by the runtime, not by your code. Effects are encoded as types (Task)
  • You can tell by looking at the type signature whether or not a function has side effects

Immutability

x = x + 1
  • All data is immutable, making code easier to think about
  • Immutable data makes code easier to think about
  • You don't have to worry about your data being changed out from under you

Designed For Frontend

  • Elm is designed to bring FP to FE devs, not FP devs to the Frontend
  • It eschews concepts that exist in other Functional Langs (like Haskell)
  • Concepts like Signals are key to the language, but pacakges are available to abstract that away

Tooling

  • Elm REPL
  • Elm Make
  • Elm Package Manager
  • Elm Reactor
  • Elm provides a REPL. Nothing to fancy but it's good for testing things out
  • Elm Make is simple build system
  • Elm Package Manager is a (yet another) package manager. It provides nice installation plan. It enforces SemVer.
  • Elm Reactor provides easy re-compilation (just refresh the page) of a project, hotswapping and a time-traveling debugger (think Brent Victor Inventing On Principle).

Elm Syntax

Crash Course
  • Elm is an ML style language, like Haskell.
  • It can seem a littl strange at first, so here's a crash course

Functions

add x y = x + y

add 10 11 -- 21

add' = (\x y -> x + y) -- anonymous function
            

Pattern Matching

or b1 b2 =
  case b1 of
    True -> True
    False -> b2
            
Let...In
f x =
  let
    double = x * 2
  in
    double + double
            
  • let allows us to assign names to values, or define functions in a limited scope

Lists

xs = [1, 2, 3]

4::xs -- [4, 1, 2, 3]

head xs
  case xs of
    x::xs -> Just x
    []    -> Nothing
            

Tuples

t = (1, "Foo")
t' = (2, "Bar", [1, 2, 3])
            

Union Types

type Action =
  Add
| Sub
            
calc action n m =
  case action of
    Add -> n + m
    Sub -> n - m

calc Add 1 2 -- 3

calc Sub 5 3 -- 2
            
  • Unions are like enums in other languages, but have more power as we'll see later

Union Types

With Values
type Action =
  Increment
| Decrement

type Counter = Counter Int
            

step action (Counter n)=
  case action of
    Increment -> Counter (n + 1)
    Decrement -> Counter (n - 1)

step Increment (Counter 1) -- Counter 2

step Decrement (Counter 2) -- Counter 1
            
  • This example is fairly trivial, but the point is that each value of a type can carry data
  • The point is they can hold any data

Polymorphic Unions

type Maybe a =
  Just a
| Nothing

type Either a b =
  Left a
| Right b
            
  • types can carry data with them, and we can parameterize that data
  • Here 'a' is a type variable
  • Maybe a isn't a "concrete" type, it's a like a function waiting for an argument
  • Maybe Int & Maybe Char are concrete types

Records

Defining & Accessing
person = { first = "Jane", last = "Smith" }

person.first -- "Jane"

.last person -- "Smith"

List.map .last people -- a list of last names

sayHi { first } =
  "Hi " ++ first

sayHi person -- "Hi Jane"
            
  • Records are like objects / hashes in other languages
  • But records in Elm are far more powerful than, say, objects in JS
  • They are also very similar to n-tuples or a sum type containing various values
  • Records, however, come with accessors (which are just functions), provide a more familiar interface

Records

Updating
{ person - first } -- removes a field

{ person | age = 20 } -- adds a new field & value

{ person | first <- "John" } -- updates a field

{ person - last | surname = "Smith" }
-- combine adding & deleting to rename a field
            
  • Important note here, this is not mutation, data is immutable.
  • Each operation creates a new record, using the source as a template

Types

The Part Where Everyone Stops Listening
  • The idea of a statically typed languages turns a lot of people off
  • But notice that none of the previous examples have type annotations
  • Yet each expression has a type and is statically checked at compile time
  • Elms type inference sorts all of that out
  • You don't NEED to annotate your code, but you should.
  • Types can help guide an implmentation, and they provide documentation

Examples of Types

5 : number

4.5 : Float

"Hi" : String

'c' : Char

Keyboard.presses : Signal Int

person : {first : String, last : String}

add : Int -> Int -> Int

map : (a -> b) -> List a -> List b
            
  • Numbers in Elm can be a float or an int, but Elm also includes the broader 'number'
  • number is a type that could be a Float or an Int depending on the usage
  • Signals play a HUGE role in Elm. Unfortunately, the topic is too large to get into now
  • The type of a function is a list of argument types, separated by '->'
  • The final type in the signature is the return type
  • Polymorphic functions look like regular functions, except types are replaced by type variables
  • The type variable 'a' will stand for the same type throughout the signature
  • 'a' and 'b' CAN be different types, but are not required to be

Demo

Further

Thanks!

@thunk_life
https://thunklife.github.io/elm-talk