Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access fields of a Union in Elm?

Tags:

elm

I am learning the programming language Elm. I want to access a particular field of a union. I am unable to access it. I have searched in the documentation. But I could not find anywhere how to access a particular field of a Union. The code is as follows:

import Graphics.Element exposing (show)
import List exposing (length, filter, map)

type Person 
  = Person { fname: String, lname: String, age: Int}

p1 = Person { fname="ABC", lname="XYZ", age=23 }
p2 = Person { fname="JK", lname="Rowling", age=24 }

-- These are unions with fields

people : List Person
people = [ p1
         , p2
         , Person {fname= "Anakin", lname= "Luke", age= 12}
         ]

main = show [people]

I cannot use p1.name since p1 is not a record. How do I access the field fname of p1 or p2?

like image 952
Chetan Yewale Avatar asked Mar 16 '23 10:03

Chetan Yewale


1 Answers

The documentation on the website is still getting improved, and need some more links between different parts. The documentation you're looking for is here.

Case expressions

The relevant part explains that a union type can have different tagged values, so you need a case-expression to distinguish the different options:

case p1 of
  Person r -> r.fname

Let expressions

Since in your case there is only one option, you can also safely use a deconstruction pattern in a variable assignment:

(Person p1Record) = p1
-- now p1Record is defined, and you can use p1Record.fname

Be careful with let expressions

Note that if you use this assignment trick for a union type with multiple tags, you open your program up to runtime crashes. The crash will happen if the value you try to deconstruct is not of the right tag:

type Direction
  = Left
  | Right
  | Forward
  | Back

march : Direction -> Boolean
march dir =
  let
    Forward = dir -- contrived example
  in
    True

main =
  show (march Back) -- oops, runtime crash

Final note

Since your union type has only one tag, you may want to consider using a type alias instead. It's just a utility to write a nicer name for a type, but you don't have to unwrap it to use the inner type:

type alias Person 
  = {fname: String, lname: String, age: Int}

p1 = {fname= "ABC", lname= "XYZ", age= 23}
-- p1.fname is immediately accessible
like image 84
Apanatshka Avatar answered Mar 22 '23 23:03

Apanatshka