introduction to elm
TRANSCRIPT
INTRODUCTION TO ELM
WHAT IS ELM?
2
•4 years old language
•Compile to JS
•Front-end focus
•Simplicity focus
•FRP focus
CHARACTERISTICS
3
•Functional
•ML syntax
•Immutability
•Pure functions
•Strong type system, but:
•No typeclasses
•No higher kinded types
•Functional reactive programming
4
DO I REALLY NEED TO LEARNA NEW LANGUAGE?
LET’S JUST USE JAVASCRIPT!
5
Elm
JS ES6 + Babel + Webpack + React + Redux + Immutableor
Typescriptor
Brunchor
Gulpor
Grunt
or
Cycle.js + RxJSor
seamless- immutableNot even close
6
ELM MAKEThe compiler that talks to you
7
8
9
NO RUNTIME EXCEPTIONS
10
NO RUNTIME EXCEPTIONS
11
12
A LITTLE MORE OBVIOUS SYNTAX
-- isNotEven = not . isEvenisNotEven = not << isEven
isNotEven' = isEven >> not
-- let lastChar = head $ toList $ reverse "foobar"let lastChar = head <| toList <| reverse "foobar"
dot = scale 2 (move (20,20) (filled blue (circle 10)))
dot' = circle 10 |> filled blue |> move (20,20) |> scale 2
13
RECORDScarolina = { name = "Carolina de Jesus" , age = 62 }
abdias = { name = "Abdias Nascimento" , age = 97 } people = [ carolina , abdias ]
carolina.name
.name carolina
List.map .name people-- ["Carolina de Jesus", "Abdias Nascimento"]
14
ELM REPLJust a regular REPL
15
16
17
ELM PACKAGEThe best package manager ever
18
ENFORCED SEMVER
19
ENFORCED SEMVER
20
AUTOMATIC CHANGELOG
21
ENFORCED DOCS
22
ELM REACTORAwesome development flow
ELM REACTOR
23
•Auto compile Elm
•Hot-swapping
•Time travel debugging
25
THE ELM ARCHITECTURE
26
SIGNALS
import Graphics.Element exposing (..)import Mouse
main : Signal Elementmain = Signal.map show Mouse.position
27
Update
Model
Viewaction
signal mailbox
28
talk is cheap, show me the code
29
moduleCounterwhere
importHtmlexposing(..)importHtml.Attributesexposing(style)importHtml.Eventsexposing(onClick)
--MODEL
typealiasModel=Int
--UPDATE
typeAction=Increment|Decrement
update:Action->Model->Modelupdateactionmodel=caseactionof
COUNTER.ELM
--UPDATE
typeAction=Increment|Decrement
update:Action->Model->Modelupdateactionmodel=caseactionofIncrement->model+1
Decrement->model-1
--VIEW
view:Signal.AddressAction->Model->Htmlviewaddressmodel=div[][button[onClickaddressDecrement][text"-"],div[countStyle][text(toStringmodel)],button[onClickaddressIncrement][text"+"]
30
COUNTER.ELM
--VIEW
view:Signal.AddressAction->Model->Htmlviewaddressmodel=div[][button[onClickaddressDecrement][text"-"],div[countStyle][text(toStringmodel)],button[onClickaddressIncrement][text"+"]]
countStyle:AttributecountStyle=style[("font-size","20px"),("font-family","monospace"),("display","inline-block"),("width","50px"),("text-align","center")]
31
COUNTER.ELM
32
MAIN.ELM
importCounterexposing(update,view)importStartApp.Simpleexposing(start)
main=start{model=0,update=update,view=view}
http://evancz.github.io/elm-architecture-tutorial/examples/1
33
side-effects
34
EFFECTS
type Action = RequestMore | NewGif (Maybe String)
update : Action -> Model -> (Model, Effects Action)update action model = case action of RequestMore -> (model, getRandomGif model.topic)
NewGif maybeUrl -> ( Model model.topic (Maybe.withDefault model.gifUrl maybeUrl) , Effects.none )
35
TASKS
getRandomGif : String -> Effects ActiongetRandomGif topic = Http.get decodeUrl (randomUrl topic) |> Task.toMaybe |> Task.map NewGif |> Effects.task
randomUrl : String -> StringrandomUrl topic = Http.url "http://api.giphy.com/v1/gifs/random" [ "api_key" => "dc6zaTOxFJmzC" , "tag" => topic ]
36
invention or discovery?
37
try to escape the Elm Architecture, I dare you!
38
TESTSOnly for checking what the compiler can’t
39
ELM TEST
module Example where
import ElmTest exposing (..)
tests : Testtests = suite "A Test Suite" [ test "Addition" <| assertEqual (3 + 7) 10
, test "This test should fail" <| assert False ]
40
ELM TEST BDD STYLE
module Example where
import ElmTestBDDStyle exposing (..)
tests : Testtests = describe "A Test Suite" [ it "adds two numbers" <| expect (3 + 7) toBe 10
, it "fails for non-sense stuff" <| expect True toBe False ]
41
PROPERTY-BASED TESTINGmodule Example where
import ElmTestBDDStyle exposing (..)import Check.Investigator exposing (..)
tests : Testtests = describe "A Test Suite" [ it "adds two numbers" <| expect (3 + 7) toBe 10
, it "fails for non-sense stuff" <| expect True toBe False
, itAlways "ends up with the same list when reversing twice" <| expectThat (\list -> List.reverse (List.reverse list)) isTheSameAs (identity) forEvery (list int) ]
42
JS
JAVASCRIPT INTEROP
Avoid it at all costs
43
FROM JS TO ELM
port addUser : Signal (String, UserRecord)
myapp.ports.addUser.send([ "Tom", { age: 32, job: "lumberjack" }]);
myapp.ports.addUser.send([ "Sue", { age: 37, job: "accountant" }]);
JS
44
FROM ELM TO JS
port requestUser : Signal Stringport requestUser = signalOfUsersWeWantMoreInfoOn
myapp.ports.requestUser.subscribe(databaseLookup);
function databaseLookup(user) { var userInfo = database.lookup(user); myapp.ports.addUser.send(user, userInfo);}
JS
45
NATIVE JS INTEROP
DON’T USE THIS
THANK YOU