Herramientas de usuario

Herramientas del sitio


wiki2:elm

¡Esta es una revisión vieja del documento!


Elm

Starting

When starting a project you will launch the next command:

elm init

You can add Elm code to src folder. For example Main.elm:

import Html
main = Html.text "Hello world"

You can see its result with the next command launching the elm file.

elm reactor

After this you can create a public folder and put there the next index.html code file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>MY COOL ELM APP</title>
</head>
<body>
    <div id="hello-world"></div>
    <script src="main.js"></script>
    <script>
        const myDiv = document.getElementById("hello-world");
        const app = Elm.Main.init({ node: myDiv });
    </script>
</body>
</html>

You can compile the elm file with:

elm make src/Main.elm --output public/main.js

Functional programming concepts

A higher order function is a function that operates with functions in a way that takes a function as an argument, or returns a function.

A combinator function is a function that only relies on those functions that are passed as arguments.

A curried function is a function partly applied. For example, having this one:

getIds users = List.map (\u -> u.userId) users

We can write it like this:

getIds = List.map .userId

In this way getIds returns another function which is a map that will extract the userId paramater from what is passed to the previous function.

Free variables are those that are not taken from function arguments.

A closure is a persistent local variable scope. The scope is kept for local variables even after the code execution has moved out of that block. In the next JS code we have an outer function which will return the inner function. The variable a is defined inside outer and has that scope, however, it is accessed when inner is called.

outer = function() {
  var a = 1;
  var inner = function() {
    console.log(a);
  }
  return inner; // this returns a function
}
var fnc = outer(); // execute outer to get inner 
fnc();

In Elm we can achieve a closure returning a function:

> stringRepeater n = \s -> String.repeat n s
<function> : Int -> String -> String
> twentyTimesString = stringRepeater 20
<function> : String -> String
> twentyTimesString "a"
"aaaaaaaaaaaaaaaaaaaa" 

Basic

Records

Constructing:

type alias User = { userId: Int, name: String }
User 1 "John"

For each record type alias, the compiler automatically generates a constructor function of the same name. The constructor is a regular function so it can be partially applied:

User 1

Extending records in the next two ways:

type alias GenericNode a = { a | 
	actualLoops : Int, actualRows : Int,
	actualStartupTime : Float,
	actualTotalTime : Float
	}
type alias CteNode = GenericNode
	{ 
		nameAlias : String
	}
-- A CteNode is a record with all the fields of GenericNode plus an additional alias field.

Type annotation

To declare a function (type anotation) that gets a number and returns an string:

checkStatus : Int -> String

If you write “checkStatus” it will return <function> : Int -> String.

It is something like this:

<function: add> : Int      -> Int      -> Int
| function name | type arg1 | type arg2 | type result |

Other ways to define a type:

coordinates : (Float, Float)
coordinates = (53.1201749, 8.5962037)

list : List number
list = [ 1, 2, 3, 4 ]

rect : { width : Int, height : Int }
rect = { width = 10, height = 20 }

Types

Something similar to an enum is this:

type UserStatus = Regular | Visitor

Where UserStatus only can have values Regular or Visitor.

type UserStatus
  = Regular
  | Visitor

type alias User =
  { status : UserStatus
  , name : String
  }

thomas = { status = Regular, name = "Thomas" }
kate95 = { status = Visitor, name = "kate95" }

Other way to the previous code:

type User
  = Regular String
  | Visitor String

thomas = Regular "Thomas"
kate95 = Visitor "kate95"

Lets see:

type User
  = Regular String Int
  | Visitor String
-- A regular user has name and age; a visitor, only name.
Regular
-- <function> : String -> Int -> User
Visitor
-- <function> : String -> User
Regular "Thomas" 44
-- Regular "Thomas" 44 : User
Visitor "kate95"
-- Visitor "kate95" : User

Type Aliases

A type alias is a shorter name for a type. For example, you could create a User alias like this:

type alias User =
  { name : String
  , age : Int
  }

-- WITH ALIAS

isOldEnoughToVote : User -> Bool
isOldEnoughToVote user =
  user.age >= 18


-- WITHOUT ALIAS. You would need to always manage the whole structure itself.

isOldEnoughToVote : { name : String, age : Int } -> Bool
isOldEnoughToVote user =
  user.age >= 18

As I understand you could pattern match a type, but not a type alias. We specify the type of functions like update and view with type aliases.

An Elm Program

There are two ways to insert an Elm program in your browser. As Browser.sandbox or Browser.element. The first one does not have external communication and is good to just create an Elm program that does not interlopes with the browser apart from creating html tags, the second one allows to access to REST services, time, random…

Program structure

The next code is basic program structure. It uses Browser.sandbox to create the end html. Browser.sandbox receives an init value (Which is the model), an update function, and a view function.

module Marcarrones exposing (..)
 
import Browser
import Html exposing (..)
import Html.Events exposing (onClick)
 
main = Browser.sandbox { init = 0, update = update, view = view }
 
-- Where we create a variable Model we are creating an Int
type alias Model = Int
 
-- Update is a function that receives two ints and returns an int
update : Model -> Int -> Int            
-- (Basic implementation) First int parameter is "inccrement", Second int is "model", 
-- update increment model = model + increment
-- Adding an "if expression"
update increment model = if increment == 0 then 0 else model + increment
 
-- This is the standard way of a view function 
view : Model -> Html Model
-- View receives a parameter Model called model; it returns an Html and the changed model
view model =                            
    div []
        [ 
            -- A button "object" with the onClick method (onClick calls update when the button is pressed)
            button [ onClick 1 ] [ text "Add" ],        
            div [] [ text (String.fromInt model) ],
            button [ onClick -1 ] [ text "Subs" ],
            div [] [
                button [ onClick 0 ] [ text "Reset" ]
            ]
        ]
wiki2/elm.1589021279.txt.gz · Última modificación: 2020/05/09 11:48 (editor externo)