Синтаксис записи кажется чрезвычайно удобным по сравнению с необходимостью писать собственные функции доступа. Я никогда не видел, чтобы кто-нибудь давал какие-либо рекомендации относительно того, когда лучше всего использовать синтаксис записи над синтаксисом объявления нормальных данных, поэтому я просто спрошу здесь.
Когда следует использовать синтаксис записи для объявлений данных в Haskell?
Ответ 1
Вы должны использовать синтаксис записи в двух ситуациях:
- Тип имеет много полей
- Объявление типа не дает никакого представления о его предполагаемом макете
Например, тип Point можно просто объявить как:
data Point = Point Int Int deriving (Show)
Очевидно, что первый Int обозначает координату x, а второй обозначает y. Но случай со следующим объявлением типа отличается (взято из Learn You a Haskell for Great Good):
data Person = Person String String Int Float String String deriving (Show)
Предполагаемый тип макета: имя, фамилия, возраст, высота, номер телефона и любимый аромат мороженого. Но это не очевидно в вышеупомянутой декларации. Здесь удобно использовать синтаксис записи:
data Person = Person { firstName :: String
, lastName :: String
, age :: Int
, height :: Float
, phoneNumber :: String
, flavor :: String
} deriving (Show)
Синтаксис записи сделал код более читаемым и сохранил большое количество ввода, автоматически определяя все функции доступа для нас!
Ответ 2
В дополнение к сложным многопользовательским данным, newtype
часто определяются с синтаксисом записи. В любом из этих случаев на самом деле нет недостатков в использовании синтаксиса записи, но в случае типов сумм записи доступа обычно не имеют смысла. Например:
data Either a b = Left { getLeft :: a } | Right { getRight :: b }
является допустимым, но функции доступа являются частичными - это ошибка для записи getLeft (Right "banana")
. По этой причине такие аксессоры, как правило, обескуражены; что-то вроде getLeft :: Either a b -> Maybe a
будет более распространенным, и это нужно будет определить вручную. Однако обратите внимание, что аксессоры могут использовать имена:
data Item = Food { description :: String, tastiness :: Integer }
| Wand { description :: String, magic :: Integer }
Теперь description
является суммарным, хотя tastiness
и magic
все еще не являются.