My wife's great tip on how I should open my presentation is to tell you more about myself, because according to her, it helps create interest in the presentation, which again according to her, is way too technical, and super boring, and she hardly thinks anyone will come, let alone enjoy it.
gizra // @amitaibu

Elm

A different approach to frontend webapps
Counter.elm

module Counter where

import Html exposing (..)
import Html.Events exposing (onClick)

-- MODEL

type alias Model = Int

init : Int -> Model
init count = count

-- UPDATE

type Action = Increment | Decrement

update : Action -> Model -> Model
update action model =
  case action of
    Increment -> model + 1
    Decrement -> model - 1

-- VIEW

view : Signal.Address Action -> Model -> Html
view address model =
  div []
    [ button [ onClick address Decrement ] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [ onClick address Increment ] [ text "+" ]
    ]
          

Elm Architecture

Principle 1: Single source of truth

The state of your whole application is stored in a record tree

Principle 2: State is read-only

The only way to mutate the state is to emit an action describing what happened
						
module Person where

import Effects exposing (Effects)
import Html exposing (button, div, pre, text, Html)
import Html.Events exposing (onClick)

-- MODEL

type alias Model =
  { age  : Int
  , kids : Int
  , name : String
  }

initialModel : Model
initialModel =
  { age  = 38
  , kids = 3
  , name = "Amitai"
  }

init : (Model, Effects Action)
init =
  ( initialModel
  , Effects.none
  )

-- UPDATE

type Action = Decrement | Increment

update : Action -> Model -> (Model, Effects Action)
update action model =
  case action of
    Decrement ->
      ( { model | kids = model.kids - 1 }
      , Effects.none
      )

    Increment ->
      ( { model | kids = model.kids + 1 }
      , Effects.none
      )

						
					
						
view : Signal.Address Action -> Model -> Html
view address model =
  div []
    [ div [] [ text <| "Name: " ++ model.name ]
    , div [] [ text <| "Age: " ++ (toString model.age) ]
    , div [] [ text <| "Kids num: " ++ (toString model.kids) ]
    , button [ onClick address Decrement ] [ text "-" ]
    , button [ onClick address Increment ] [ text "+" ]
    , pre [] [ text (toString model) ]
    ]





--
						
					
						
view : Signal.Address Action -> Model -> Html
view address model =
  div []
    [ viewName model.name
    , viewAge  model.age
    , viewKids model.age
    , button [ onClick address Decrement ] [ text "-" ]
    , button [ onClick address Increment ] [ text "+" ]
    , pre [] [ text (toString model) ]
    ]

viewName : String -> Html
viewName name =
  div [] [ text <| "Name: " ++ name ]

viewAge : Int -> Html
viewAge age =
  div [] [ text <| "Age: " ++ (toString age) ]

viewKids : Int -> Html
viewKids kids =
  div [] [ text <| "Kids num: " ++ (toString kids) ]
						
					

Compile Error Vs Runtime Mistakes

Types 101

						
type Bool = False | True
						
					
						
type Vehicle = Boat | Plane | Car Int

type alias Model =
  { name    : String
  , vehicle : Vehicle
  }
						
					

Type Safety

						
--

type alias Model =
  { age  : Int
  , kids : Int
  , name : String
  }

initialModel : Model
initialModel =
  { age  = 38
  , kids = 3
  , name = "Amitai"
  }
						
					
						
type Kids = Kids Int

type alias Model =
  { age  : Int
  , kids : Kids
  , name : String
  }

initialModel : Model
initialModel =
  { age  = 38
  , kids = Kids 3
  , name = "Amitai"
  }

						
					
						
viewKids : Int -> Html
viewKids kids =
  div [] [ text <| "Kids num: " ++ (toString kids) ]


--
						
					
						
viewKids : Kids -> Html
viewKids kids =
  let
    (Kids val) = kids
  in
    div [] [ text <| "Kids num: " ++ (toString val) ]
						
					
						
viewKids : Kids -> Html
viewKids (Kids kids) =
  div [] [ text <| "Kids num: " ++ (toString val) ]


--
						
					
						
update : Action -> Model -> (Model, Effects Action)
update action model =
  case action of
    Decrement ->
      ( { model | kids = model.kids - 1 }
      , Effects.none
      )

    Increment ->
      ( { model | kids = model.kids + 1 }
      , Effects.none
      )




--
						
					
						
update : Action -> Model -> (Model, Effects Action)
update action model =
  case action of
    Decrement ->
      let
        (Kids val) = model.kids
        kids' = Kids (val - 1)
      in
        ( { model | kids = kids' }
        , Effects.none
        )

    Increment ->
      let
        (Kids val) = model.kids
        kids' = Kids (val + 1)
      in
        ( { model | kids = kids' }
        , Effects.none
        )
						
					

40 seconds of my life

Put a limit on Kids

						
update : Action -> Model -> (Model, Effects Action)
update action model =
  case action of
    Decrement ->
      let
        (Kids val) = model.kids
        kids' = Kids (val - 1)
      in
        ( { model | kids = kids' }
        , Effects.none
        )

    Increment ->
      let
        (Kids val) = model.kids
        kids' = Kids (val + 1)
      in
        ( { model | kids = kids' }
        , Effects.none
        )
						
					
						
update : Action -> Model -> (Model, Effects Action)
update action model =
  case action of
    Decrement ->
      let
        (Kids val) = model.kids
        kids' = if val < 1 then Kids 0 else Kids (val - 1)
      in
        ( { model | kids = kids' }
        , Effects.none
        )

    Increment ->
      let
        (Kids val) = model.kids
        kids' = if val > 4 then Kids 5 else Kids (val + 1)
      in
        ( { model | kids = kids' }
        , Effects.none
        )
						
					

Buisness Logic requires Testing

Unit tests

Pure Functions & Side Effects


 -- MODEL
 type alias Model = Int

 -- UPDATE
 type Action
   = GetDataFromServer
   | UpdateDataFromServer Result
           

 GetDataFromServer ->
   ( model, Http.get "https://example.com/api/data" |> Task.map UpdateDataFromServer )

 UpdateDataFromServer result ->
   case result of
     Ok val ->
       ( { model = val } , Effects.none )
     Err msg ->
       ( model , Effects.none )

           

Headless Drupal

https://github.com/amitaibu/elm-hedley

Yeoman Generator

https://github.com/Gizra/generator-elmlang
  • Gulp
  • browserSync
  • Auto-compile
  • Sass
  • Bundle and Deploy to gh-pages

My functional programming journey

What about NodeJs?
gizra | We now have a US office. Seriously.