DEV Community

blackode
blackode

Posted on

1010 Killer elm Tips to code like a master

Pro elm tips to write code like a pro

designed using https://crello.comdesigned using https://crello.com

The using elm in production involves teaching and learning. This article comprises of 10 killer pro elm tips that you may or may not know.

0001 — type alias as a function

The type aliases can be used as functions to construct a new value.

> type alias User = { name: String, age: Int }
> user = User "john" 23
{ name = "john", age = 23 } : Repl.User
> user
{ name = "john", age = 23 } : Repl.User
Enter fullscreen mode Exit fullscreen mode

You have to just pass the initial values in the order of the type alias definition.

0010 — calling infix functions

In elm, almost everything is a function or can act like a function.

The addition operation in elm is just a function call using +. The definition of the + is like

(+) : number -> number -> number
Enter fullscreen mode Exit fullscreen mode

The type specs clearly tell you that it takes two number parameters and returns a number. The way of calling this function is different because it is Infix function.

Infix functions are the functions whose name is in between the parameters. The left side parameter is passed as the first parameter and the right parameter is passed as the second parameter.

example: 1+2

In the above example, + is the function name and 1,2 are its parameters where 1 is the first parameter and 2 is the second parameter.

You can also call the infix function by wrapping function name inside the parenthesis () like (+).

> (+) 1 2
3 : number

-- which is the same as calling 
> 1 + 2
3: number
Enter fullscreen mode Exit fullscreen mode

0011 — function composition

As you know elm is everywhere functions. You can combine functions to form another function using >>

> wordCount = String.words >> List.length
<function> : String -> Int

> wordCount " Medium is full of knowledge resources"
6 : Int
Enter fullscreen mode Exit fullscreen mode

The wordCount function takes String as input and returns Int. The passed String values passed to String.words which in return gives the List String is again passed to List.length which gives Int value.

This is pretty useful.

type distributiontype distribution

0100 — point free

This point-free style coding is where you omit one or more arguments in the body of the function.

To understand this concept, look at the following examples.

Here I am trying to write a function named double which doubles the given value.

> double num = num * 2
<function> : number -> number

> double 5
10 : number
Enter fullscreen mode Exit fullscreen mode

Here, you can omit the argument num

You can do magic like

> double = (*) 2
<function> : number -> number

> double 5
10 : number

> plus = (+)
<function> : number -> number -> number

> plus 5 5
10 : number
Enter fullscreen mode Exit fullscreen mode

0101 — special function for tuple creation

In elm , you can use the (,). This is a special function used to create tuples. The magic is, it allows you to use as many , inside the ().

E.g (,,) constructs a 3-tuple and (,,,) a 4-tuple.

Check the following examples to understand this more

> (,) "apple" "banana"
("apple","banana") : ( String, String )

> (,,) "apple" 12 "banana"
("apple",12,"banana") : ( String, number, String )

> (,,,) 1 2 3 4
(1,2,3,4) : ( number, number1, number2, number3 )
Enter fullscreen mode Exit fullscreen mode

For N , you have to give N+1 args

You can use as many commas as you want. The , will act as an infix function where the function name is between the two args.

0110 — Special notation in the function definition to pattern match

Consider you have a record model with following content

> model = {name = { firstName = "john", lastName = "ankanna"}, age = 23}

{ name = { firstName = "john", lastName = "ankanna" }, age = 23 }
    : { age : number, name : { firstName : String, lastName : String } }
Enter fullscreen mode Exit fullscreen mode

If you observe the model, it has nested record name with firstName, lastName .

Suppose, you need to update the firstName field inside the model then you can do pattern match over parameters like following.

> updateFirstName ({name} as model)= {model | name = {name | firstName = "joe"}}

<function>
    : { c | name : { b | firstName : a } }
      -> { c | name : { b | firstName : String } }
Enter fullscreen mode Exit fullscreen mode

The {name} as model is a pattern matched here.

pattern matchpattern match

Now, you simple pass the defined model to the function updateFirstName to update firstName field inside name .

>updateFirstName model
{ name = { firstName = "joe", lastName = "ankanna" }, age = 23 }
    : { age : number, name : { lastName : String, firstName : String } }
Enter fullscreen mode Exit fullscreen mode

updated firstNameupdated firstName

0111 — unit type ()

A unit type is a type that allows only one value and thus can hold no information. Sometimes it is also referred to as the type of 0-tuples.

It is denoted by () and its value is same () .

> void = ()
() : ()  -- value : type are same here
Enter fullscreen mode Exit fullscreen mode

Read unit type

1000 — <| operator

This <| has lower precedence than function expression.

The f(g(h(x))) can be written as f <| g <| h x

Check the following example

> add10 = (+) 10
<function> : number -> number

> mul10 = (*) 10
<function> : number -> number

> 10 |> mul10 |> add10
110 : number

> mul10 <| add10 <| 10
200 : number
Enter fullscreen mode Exit fullscreen mode

Let us do some crazy stuff

>add = (+)
<function> : number -> number -> number

> 10 |> (add <| 10)
20 : number

> (10 |> add) <| 10
20 : number

> 10 |> add <| 10
-- SYNTAX PROBLEM -------------------------------------------- repl-temp-000.elm

Conflicting associativity for binary operators (|>, <|). Consider adding
parentheses to disambiguate.
Enter fullscreen mode Exit fullscreen mode

1001 — pattern match a list with at least elements

If you want to match a list with at least two items inside the list you can take the advantage of :: .

a :: b :: rest
Enter fullscreen mode Exit fullscreen mode

Implementation

For an example, you have to return [] if the list has items less than 2 or else you have to return the rest of the list.

  • input: [1,2,3,4,5] output: [3,4,5]
  • input: [1] output:[]
import Html exposing (text)

rest list = 
  case list of
    a :: b :: rest -> --this matches list with at least two items
      rest
    _ -> 
      []

main =
  text <| toString <| rest [1,2,3,4,5] -- returns [3,4,5]
Enter fullscreen mode Exit fullscreen mode


import Html exposing (text)

rest list = 
  case list of
    a :: b :: rest -> --this matches list with at least two items
      rest
    _ -> 
      []

main =
  text <| toString <| rest [1] -- returns []
Enter fullscreen mode Exit fullscreen mode

1010 — Similar => function in elm

> add1 = \n -> n +1
<function> : number -> number

> add1 5
6 : number
Enter fullscreen mode Exit fullscreen mode

Hope you have enjoyed the whole context.
Feel free to share and let others get benefited from you.

Happy Long Coding life :)

Top comments (0)