Читаем Изучай Haskell во имя добра! полностью

Когда имеет смысл применять типовые параметры? Обычно мы используем их, когда наш тип данных должен уметь сохранять внутри себя любой другой тип, как это делает Maybe a. Если ваш тип – это некоторая «обёртка», использование типов-параметров оправданно. Мы могли бы изменить наш тип данных Car с такого:

data Car = Car { company :: String

               , model :: String

               , year :: Int

               } deriving (Show)

на такой:

data Car a b c = Car { company :: a

                     , model :: b

                     , year :: c

                     } deriving (Show)

Но выиграем ли мы в чём-нибудь? Ответ – вероятно, нет, потому что впоследствии мы всё равно определим функции, которые работают с типом Car String String Int. Например, используя первое определение Car, мы могли бы создать функцию, которая отображает свойства автомобиля в виде понятного текста:

tellCar :: Car –> String

tellCar (Car {company = c, model = m, year = y}) =

  "Автомобиль " ++ c ++ " " ++ m ++ ", год: " ++ show y

ghci> let stang = Car {company="Форд", model="Мустанг", year=1967}

ghci> tellCar stang

"Автомобиль Форд Мустанг, год: 1967"

Приятная маленькая функция. Декларация типа функции красива и понятна. А что если Car – это Car a b c?

tellCar :: (Show a) => Car String String a –> String

tellCar (Car {company = c, model = m, year = y}) =

  "Автомобиль " ++ c ++ " " ++ m ++ ", год: " ++ show y

Мы вынуждены заставить функцию принимать параметр Car типа (Show a) => Car String String a. Как видите, декларация типа функции более сложна; единственное преимущество, которое здесь имеется, – мы можем использовать любой тип, имеющий экземпляр класса Show, как тип для типовой переменной c.

ghci> tellCar (Car "Форд" "Мустанг" 1967)

"Автомобиль Форд Мустанг, год: 1967"

ghci> tellCar (Car "Форд" "Мустанг" "тысяча девятьсот шестьдесят седьмой")

"Автомобиль Форд Мустанг, год: \"тысяча девятьсот шестьдесят седьмой\""

ghci> :t Car "Форд" "Мустанг" 1967

Car "Форд" "Мустанг" 1967 :: (Num t) => Car [Char] [Char] t

ghci> :t Car "Форд" "Мустанг" "тысяча девятьсот шестьдесят седьмой"

Car "Форд" "Мустанг" "тысяча девятьсот шестьдесят седьмой"

  :: Car [Char] [Char] [Char]

На практике мы всё равно в большинстве случаев использовали бы Car String String Int, так что в параметризации типа Car большого смысла нет. Обычно мы параметризируем типы, когда для работы нашего типа неважно, что в нём хранится. Список элементов – это просто список элементов, и неважно, какого они типа: список работает вне зависимости от этого. Если мы хотим суммировать список чисел, то в суммирующей функции можем уточнить, что нам нужен именно список чисел. То же самое верно и для типа Maybe. Он предоставляет возможность не иметь никакого значения или иметь какое-то одно значение. Тип хранимого значения не важен.

Ещё один известный нам пример параметризованного типа – отображения Map k v из модуля Data.Map. Параметр k – это тип ключей в отображении, параметр v – тип значений. Это отличный пример правильного использования параметризации типов. Параметризация отображений позволяет нам использовать любые типы, требуя лишь, чтобы тип ключа имел экземпляр класса Ord. Если бы мы определяли тип для отображений, то могли бы добавить ограничение на класс типа в объявлении:

data (Ord k) => Map k v = ...

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных