Как получить доступ к полям союза в Elm?

Я изучаю язык программирования Elm. Я хочу получить доступ к определенному полю объединения. Я не могу получить к нему доступ. Я искал в документации. Но я нигде не мог найти, как получить доступ к тому или иному полю Союза. Код выглядит следующим образом:

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]

Я не могу использовать p1.name, так как p1 не является записью. Как получить доступ к полю fname из p1 или p2?


elm
person Chetan Yewale    schedule 11.07.2015    source источник


Ответы (1)


Документация на веб-сайте все еще совершенствуется, и ей нужны дополнительные ссылки между различными частями. Документация, которую вы ищете, находится здесь.

Выражения регистра

В соответствующей части объясняется, что тип объединения может иметь разные значения тегов, поэтому вам нужно выражение case-expression, чтобы различать разные варианты:

case p1 of
  Person r -> r.fname

Пусть выражения

Поскольку в вашем случае есть только один вариант, вы также можете смело использовать шаблон деконструкции в присваивании переменной:

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

Будьте осторожны с выражениями let

Обратите внимание, что если вы используете этот прием присваивания для типа объединения с несколькими тегами, вы открываете свою программу для сбоев во время выполнения. Сбой произойдет, если значение, которое вы пытаетесь деконструировать, не относится к правильному тегу:

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

Последнее примечание

Поскольку ваш тип объединения имеет только один тег, вы можете рассмотреть возможность использования вместо него type alias. Это просто утилита для написания более красивого имени для типа, но вам не нужно разворачивать его, чтобы использовать внутренний тип:

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

p1 = {fname= "ABC", lname= "XYZ", age= 23}
-- p1.fname is immediately accessible
person Apanatshka    schedule 11.07.2015
comment
Мне нравится пример псевдонима типа. Это наиболее уместно. Я просмотрел документацию. Скажите, прав ли я: 1. Псевдонимы типов — это средство для создания типов записей, верно? 2. Я попробовал предложенный вами шаблон деконструкции: Person p1Record = p1. А потом попробовал использовать p1Record.name. Но это дает мне ошибку компиляции. - person Chetan Yewale; 12.07.2015
comment
Хорошо, как ни странно, вам нужно заключать в скобки совпадение с шаблоном, даже если это единственный шаблон: (Person p1Record) = p1. Спасибо за продолжение, ‹del›я отредактирую свой ответ‹/del›‹ins›done‹/ins›. - person Apanatshka; 12.07.2015
comment
Chetan496, чтобы ответить на ваш другой вопрос: псевдоним типа - это общее средство для присвоения типу другого имени. Но если вы непосредственно определяете псевдоним типа для записи, он также сгенерирует конструктор, поэтому вам не нужно использовать синтаксис записи: type alias Rec = { hi: String, ih: Int } определяет функцию Rec : String -> Int -> Rec, а также тип. - person Apanatshka; 12.07.2015
comment
Спасибо, Апанашка, за информацию. Я не знал, что псевдонимы типов определяют не только функцию, но и тип. - person Chetan Yewale; 14.07.2015