Доступ к членам пользовательского типа данных в Haskell
Скажем, у меня есть следующие пользовательские типы данных и функции в Haskell:
data Person = Person { first_name :: String,
last_name :: String,
age :: Int
} deriving (Eq, Ord, Show)
Если я хочу создать функцию print_age
, чтобы напечатать возраст Person, вот так: print_age (Person "John" "Smith" 21)
, как бы я написал print_age
для доступа к возрастному параметру? Я - объектно-ориентированный парень, поэтому я вне себя от своего элемента. Я в основном ищу эквивалент Person.age.
Ответы
Ответ 1
Назначение функций - это префикс, поэтому age person
будет соответствовать общему значению person.age()
в языках ООП. Функция print_age
может быть определена как беспотенциальная по композиции функций
print_age = print . age
или point-full
print_age person = print (age person)
Ответ 2
Это называется синтаксисом записи, LYAH имеет хороший раздел на нем (ctrl-f для синтаксиса записи).
Когда тип данных определяется с записями, Haskell автоматически определяет функции с тем же именем, что и запись, чтобы действовать как аксессоры, поэтому в этом случае age
является аксессором для поля возраста (у него есть тип Person -> Int
), и аналогично для first_name
и last_name
.
Это обычные функции Haskell и поэтому называются как age person
или first_name person
.
Ответ 3
В дополнение к функции age
, упомянутой в других ответах, иногда удобно использовать сопоставление образцов.
print_age Person { age = a } = {- the a variable contains the person age -}
Существует довольно безобидное расширение, которое позволяет пропустить бит именования:
{-# LANGUAGE NamedFieldPuns #-}
print_age Person { age } = {- the age variable contains the person age -}
... и другой, рассматриваемый с различной степенью недоверия со стороны различных членов сообщества, что позволяет вам даже пропустить, какие поля вы хотите ввести в объем:
{-# LANGUAGE RecordWildCards #-}
print_age Person { .. } = {- first_name, last_name, and age are all defined -}