Elm is a functional language that compiles to JavaScript.
No combination of JS libraries can ever give you this, yet it is all free and easy in Elm.
No Runtime Exceptions *
Great Performance
Static types
Algebraic data types (ADT)
Immutability
Anonymous records
Parametric polymorphism
Compile to Javascript
import Html exposing (span, text)
import Html.Attributes exposing (style)
main =
span
[style [("color", "red")]]
[text "Hello, World!"]
Easy as ABC
True : Bool
False : Bool
42 : number -- Int or Float depending on usage
3.14 : Float
'a' : Char
"abc" : String
True && not (True || False)
(2 + 4) * (4^2 - 9)
"abc" ++ "def"
(0, True, 'z', "abc")
(,) 1 2 == (1,2)
(,,,) 1 True 'a' [] == (1,True,'a',[])
[1,2,3,4]
1 :: [2,3,4]
1 :: 2 :: 3 :: 4 :: []
['a', 'b', 'c']
["a", "b", "c"]
square n =
n^2
hypotenuse a b =
sqrt (square a + square b)
distance (a,b) (x,y) =
hypotenuse (a-x) (b-y)
multiply a b = a * b
multiplyByThree = multiply 3
(++) [1, 2, 3] [4, 5, 6]
List.foldl (*) 1 [1, 2, 3, 4, 5]
-- function name : 1st arg type -> 2nd arg type -> return type
fnc : Int -> List Int -> Int
type Movement = Right | Left | Stop
type Maybe a = Just a | Nothing
type Result e a = Failure e | Success a
type Tree a = Tree (Tree a) a (Tree a) | Leaf
point = -- create a record
{ x = 3, y = 4 }
point.x -- access field
List.map .x [point,{x=0,y=0}] -- field access function
{ point | x = 6 } -- update a field
{ point | -- update many fields
x = point.x + 1,
y = point.y + 1
}
dist {x,y} = -- pattern matching on fields
sqrt (x^2 + y^2)
type alias Location = -- type aliases for records
{ line : Int
, column : Int
}
primitiveCount number =
case number of
1 -> "one"
2 -> "two"
3 -> "three"
4 -> "four"
_ -> "many"
case maybe of
Just xs -> xs
Nothing -> []
case xs of
hd::tl -> Just (hd,tl)
[] -> Nothing
case n of
0 -> 1
1 -> 1
_ -> fib (n-1) + fib (n-2)
module MyModule exposing (..)
-- qualified imports
import List -- List.map, List.foldl
import List as L -- L.map, L.foldl
-- open imports
import List exposing (..) -- map, foldl, concat, ...
import List exposing ( map, foldl ) -- map, foldl
import Maybe exposing ( Maybe ) -- Maybe
import Maybe exposing ( Maybe(..) ) -- Maybe, Just, Nothing
import Maybe exposing ( Maybe(Just) ) -- Maybe, Just
The logic of every Elm program will break up into three cleanly separated parts
import Html exposing (Html, beginnerProgram)
main : Program Never model msg
main =
beginnerProgram
{ model = ... -- : model
, view = ... -- : model -> Html msg
, update = ... -- : msg -> model -> model
}
import Html exposing (text)
main =
Html.beginnerProgram
{ model = ()
, view = always (text "Hello World!")
, update = always identity
}
-- always : a -> b -> a
-- identity : a -> a
import Html exposing (text, div, button)
import Html.Events exposing (onClick)
type Msg = Inc | Dec
model = 0
view model = div []
[ button [ onClick Dec ] [ text "-" ]
, text <| toString model
, button [ onClick Inc ] [ text "+" ] ]
update msg model =
case msg of
Inc -> model + 1
Dec -> model - 1
main = Html.beginnerProgram
{ model = model
, view = view
, update = update
}
import Html exposing (program)
program :
{ init : (model, Cmd msg)
, view : model -> Html msg
, update : msg -> model -> (model, Cmd msg)
, subscriptions : model -> Sub msg
}
-> Program Never model msg
type alias Model = Time
init : (Model, Cmd Msg)
init =
(0, Cmd.none)
type Msg
= Tick Time
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Tick newTime ->
(newTime, Cmd.none)
subscriptions : Model -> Sub Msg
subscriptions model =
Time.every second Tick
view : Model -> Html Msg
view model =
Html.text (toString model)
type alias Model = Int
type Msg
= GenerateNumber
| SetNumber Int
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
GenerateNumber ->
( model, Random.generate SetNumber (Random.int 1 6) )
SetNumber number ->
( number, Cmd.none )
view : Model -> Html Msg
view model =
div []
[ h1 [] [ text (toString model) ]
, button [ onClick GenerateNumber ] [ text "Generate" ]
]
We do not think in terms of reusable components.
Instead, we focus on reusable functions. It is a functional language after all!
elm-repl — play with Elm expressions
elm-reactor — get a project going quickly
elm-make — compile Elm code directly
elm-package — download packages
$ elm-make Main.elm --output elm.js
<div id="elm-code-is-loaded-here"></div>
<script src="elm.js"></script>
<script>
Elm.Main.embed(document.getElementById("elm-code-is-loaded-here"));
</script>
$ ls -lhS
566K Jan 4 22:03 angular2.min.js
563K Jan 4 22:05 angular2.0.0-beta.0-all.umd.min.js
486K Jan 4 21:50 ember.1.13.8.min.js
435K Jan 4 21:48 ember.2.2.0.min.js
205K Jan 4 22:06 angular2.0.0-beta.0-Rx.min.js
144K Jan 4 21:59 react-with-addons-0.14.5.min.js
143K Jan 4 21:46 angular.1.4.5.min.js
132K Jan 4 21:56 react-0.14.5.min.js
121K Jan 4 21:35 angular.1.3.2.min.js
5.3K Jan 4 22:00 redux-3.0.5.min.js
706B Jan 4 21:57 react-dom-0.14.5.min.js
63K Oct 13 03:02 vue-2.0.3.min.js
# 2017
91K Dec 27 12:24 react-dom-16.2.0.production.min.js
6.5K Dec 27 12:22 react-16.2.0.production.min.js
$ elm-make Main.elm --output=main.js
$ uglifyjs ./main.js -o main.min.js -c -m
$ ls -lhS
189K Apr 7 15:32 main.js
65K Apr 7 15:37 main.min.js
Hello world Elm App size