>firstName :: Person –> String
>firstName (Person firstname _ _ _ _ _) = firstname
>lastName :: Person –> String
>lastName (Person _ lastname _ _ _ _) = lastname
>age :: Person –> Int
>age (Person _ _ age _ _ _) = age
>height :: Person –> Float
>height (Person _ _ _ height _ _) = height
>phoneNumber :: Person –> String
>phoneNumber (Person _ _ _ _ number _) = number
>flavor :: Person –> String
>flavor (Person _ _ _ _ _ flavor) = flavor
Фу-ух! Мало радости писать такие функции!.. Этот метод очень громоздкий и скучный, но он работает.
>ghci> let guy = Person "Фредди" "Крюгер" 43 184.2 "526–2928" "Эскимо"
>ghci> firstName guy
>"Фредди"
>ghci> height guy
>184.2
>ghci> flavor guy
>"Эскимо"
Вы скажете – должен быть лучший способ! Ан нет, извиняйте, нету… Шучу, конечно же. Такой метод есть! «Ха-ха» два раза. Создатели языка Haskell предусмотрели подобную возможность – предоставили ещё один способ для записи типов данных. Вот как мы можем достигнуть той же функциональности с помощью синтаксиса записей с именованными полями:
>data Person = Person { firstName :: String
> , lastName :: String
> , age :: Int
> , height :: Float
> , phoneNumber :: String
> , flavor :: String } deriving (Show)
Вместо того чтобы просто перечислять типы полей через запятую, мы используем фигурные скобки. Вначале пишем имя поля, например >firstName
, затем ставим два двоеточия >::
и, наконец, указываем тип. Результирующий тип данных в точности такой же. Главная выгода – такой синтаксис генерирует функции для извлечения полей. Язык Haskell автоматически создаст функции >firstName
, >lastName
, >age
, >height
, >phoneNumber
и >flavor
.
>ghci> :t flavor
>flavor :: Person –> String
>ghci> :t firstName
>firstName :: Person –> String
Есть ещё одно преимущество в использовании синтаксиса записей. Когда мы автоматически генерируем экземпляр класса >Show
для типа, он отображает тип не так, как если бы мы использовали синтаксис записей с именованными полями для объявления и инстанцирования типа. Например, у нас есть тип, представляющий автомобиль. Мы хотим хранить следующую информацию: компания-производитель, название модели и год производства.
>data Car = Car String String Int deriving (Show)
Автомобиль отображается так:
>ghci> Car "Форд" "Мустанг" 1967
>Car "Форд" "Мустанг" 1967
Используя синтаксис записей с именованными полями, мы можем описать новый автомобиль так:
>data Car = Car { company :: String
> , model :: String
> , year :: Int
> } deriving (Show)