Подтвердить что ты не робот

Когда следует использовать синтаксис записи для объявлений данных в Haskell?

Синтаксис записи кажется чрезвычайно удобным по сравнению с необходимостью писать собственные функции доступа. Я никогда не видел, чтобы кто-нибудь давал какие-либо рекомендации относительно того, когда лучше всего использовать синтаксис записи над синтаксисом объявления нормальных данных, поэтому я просто спрошу здесь.

4b9b3361

Ответ 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 все еще не являются.