a short introduction to Elm
Elm?
functional language
development platform
frontend architecture
ecosystem
community
ambition
no runtime exceptions
like, none
never
undefined should be a function
the Elm language
functional
Haskell but simpler
type safety
compiles to JavaScript
functional
static types
purity
immutability
functional
module system
pattern matching
type aliases
functional
pipe operators
accessor functions
JavaScript interop
import Html exposing (text)
hello : String
hello =
"Hello"
greet : String -> String
greet name =
hello ++ ", " ++ name ++ "!"
main =
text <| greet "World"
hello world
module Greetings exposing (greet)
hello : String
hello =
"Hello"
greet : String -> String
greet name =
hello ++ ", " ++ name ++ "!"
module Main exposing (main)
import Html exposing (text)
import Greetings exposing (greet)
main : Html.Html msg
main =
text <| greet "World"
module system
describeList : List String -> String
describeList list =
case list of
[] -> "No elements"
[_] -> "One element"
[a,b] -> "Two elements: " ++ a ++ " & " ++ b
a::b::_ -> "A larger list"
pattern matching
answer : String -> Maybe Int
answer question =
case question of
"universe?" ->
Just 42
_ ->
Nothing
type MyThing
= AString String
| AnInt Int
| ATuple (String, Int)
unionFn : MyThing -> String
unionFn thing =
case thing of
AString s -> "It was a string: " ++ s
AnInt i -> "It was an int: " ++ toString i
ATuple (_, _) -> "It was a string and an int"
pattern matching union types
fingerprint : String -> List Char
fingerprint word =
word
|> String.toLower
|> String.toList
|> List.sort
fingerprint_ : String -> List Char
fingerprint_ word =
List.sort
<| String.toList
<| String.toLower word
pipe operators
port module Spelling exposing (..)
-- port for sending strings out to JavaScript
port check : String -> Cmd msg
-- port for listening for suggestions from JavaScript
port suggestions : (List String -> msg) -> Sub msg
app.ports.check.subscribe(function(word) {
var suggestions = spellCheck(word);
app.ports.suggestions.send(suggestions);
});
function spellCheck(word) {
// have a real implementation!
return [];
}
JavaScript interop
a development platform
platform
compiler
REPL
debugger
$ elm-make HelloWorld.elm --output HelloWorld.js
compiling
<-- index.html -->
<head>
<script src="HelloWorld.js"></script>
</head>
<body>
<script>Elm.Main.fullscreen()</script>
</body>
The definition of `greet` does not match its type annotation.
11| greet : String -> Int
12| greet name =
13|> hello ++ ", " ++ name ++ "!"
The type annotation for `greet` says it always returns:
Int
But the returned value (shown above) is a:
String
Detected errors in 1 module.
example compiler output
Cannot find variable `nane`
13| hello ++ ", " ++ nane ++ "!"
^^^^
Maybe you want one of the following?
name
tan
Cmd.none
Sub.none
Detected errors in 1 module.
more sample compiler output
---- elm-repl 0.18.0 -----------------------------------------------------------
:help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------------------------------------------------
> shows = []
[] : List a
> shows = [1]
[1] : List number
> shows = [1, 2, 3]
[1,2,3] : List number
> isEven n = n % 2 == 0
<function> : Int -> Bool
> shows |> List.filter isEven
[2] : List Int
the REPL in action
the embedded debugger in action
platform
npm integration
package manager
semantic versioning
code autoformat
$ npm install elm
npm package available
the package manager in action
semver ftw
code autoformat
an architecture
architecture
virtual dom
model
view
update
view : Html msg
view =
div []
[ h1 [] [ text "Title" ]
, p [] [ text "Some text" ]
, ul []
[ li [] [ text "Bullet1" ]
, li [] [ text "Bullet2" ]
]
]
virtual dom
<div>
<h1>Title</h1>
<p>Some text</p>
<ul>
<li>Bullet1</li>
<li>Bullet2</li>
</ul>
</div>
entryView : List Int -> Html msg
entryView entry =
li [] [ text <| "Bullet" ++ toString entry ]
view : Model -> Html msg
view model =
div []
[ h1 [] [ text "Title" ]
, p [] [ text "Some text" ]
, ul [] <| List.map entry model.entries
]
abstract dom + functional language = <3
type Msg
= NoOp
| AddEntry String
type alias Model =
{ entries : List Int }
update : Msg -> Model -> Model
update msg model =
case msg of
NoOp ->
model
AddEntry entry ->
{ model | entries = entry :: model.entries }
a typical update function
formView : Html Msg
formView =
p [] [ input [] [ Events.onInput AddEntry ] ]
a view triggering an event
an ecosystem
hundreds of packages
a friendly community
a supportive and beginner friendly slack channel
Questions?
Elm Djangocong 2017
By Nicolas Perriault
Elm Djangocong 2017
- 873