Elm Language Records


Example

Record is a set of key-value pairs.

greeter =
    { isMorning: True
    , greeting: "Good morning!"
    }

It is impossible to access a value by an non-existent key.

It is impossible to dynamically modify Record's structure.

Records only allow you to update values by constant keys.

Accessing values

Values can not be accessed using a dynamic key to prevent possible run-time errors:

isMorningKeyName =
    "isMorning "


greeter[isMorningKeyName] -- Compiler error
greeter.isMorning -- True

The alternative syntax for accessing the value allows you to extract the value, while piping through the Record:

greeter
    |> .greeting
    |> (++) " Have a nice day!" -- "Good morning! Have a nice day!"

Extending Types

Sometimes you'd want the signature of a parameter to constrain the record types you pass into functions. Extending record types makes the idea of supertypes unnecessary. The following example shows how this concept can be implemented:

type alias Person =
    { name : String
    }


type alias Animal =
    { name : String
    }


peter : Person
peter =
    { name = "Peter" }


dog : Animal
dog =
    { name = "Dog" }


getName : { a | name : String } -> String
getName livingThing =
    livingThing.name


bothNames : String
bothNames =
    getName peter ++ " " ++ getName dog

We could even take extending records a step further and do something like:

type alias Named a = { a | name : String }
type alias Totalled a = { a | total : Int }


totallyNamed : Named ( Totalled { age : Int })
totallyNamed =
  { name = "Peter Pan"
  , total = 1337
  , age = 14
  }

We now have ways to pass these partial types around in functions:

changeName : Named a -> String -> Named a
changeName a newName =
  { a | name = newName }
  
cptHook = changeName totallyNamed "Cpt. Hook" |> Debug.log "who?"

Updating values

Elm has a special syntax for Record updates:

model =
    { id: 1
    , score: 0
    , name: "John Doe"
    }


update model =
    { model
       | score = model.score + 100
       | name = "John Johnson"
    }