Алгебраїчний тип даних (ADT) описує фіксовану кількість іменованих варіантів. Кожне значення ADT відповідає рівно одному з іменованих варіантів.
ADT визначають за допомогою ключового слова data, а варіанти розділяють символами вертикальної риски (|).
Якщо з жодним із варіантів не повʼязано даних, такий тип нагадує те, що в інших мовах зазвичай називають переліченням (або enum).
data Season
= Spring
| Summer
| Autumn
| Winter
Кожен варіант ADT може, за бажанням, мати повʼязані з ним дані, і різні варіанти можуть мати дані різних типів. Якщо з варіантом повʼязано дані, потрібен конструктор.
data Number
= NInt Int --'NInt' is the constructor for an Int Number.
| NFloat Float --'NFloat' is the constructor for an Float Number.
| Invalid --'Invalid' does not have data associated to it.
Щоб створити значення для конкретного варіанта, достатньо звернутися до його назви (наприклад, NInt 22).
Оскільки назви варіантів нічим не відрізняються від функцій-конструкторів, повʼязані дані можна передати як звичайний аргумент функції.
ADT мають структурну рівність: це означає, що два значення для одного й того самого варіанта з однаковими (необовʼязковими) даними рівнозначні.
Хоча для роботи з ADT можна використовувати вирази if/else, рекомендований спосіб - зіставлення зі зразком за допомогою інструкції case:
add1 :: Number -> String
add1 number =
case number of
NInt i -> show (i + 1)
NFloat f -> show (f + 1.0)
Invalid -> error "Invalid input"
У цій вправі ми святкуємо День Валентина і плануємо, чим зайнятися разом із партнером. У партнера безліч ідей, і він просить нас оцінити їх, щоб знайти найкраще заняття.
Ось ідеї, які пропонує партнер:
На пошук заняття на День Валентина у нас є шість завдань.
На кожну ідею, яку пропонує партнер, ми відповідаємо одним із трьох варіантів: так, ні або можливо.
Визначте алгебраїчний тип даних Approval, щоб представити ці варіанти такими трьома випадками: Yes, No або Maybe.
Партнер вибрав два можливі ресторани: один із корейською кухнею, а другий із турецькою.
Визначте алгебраїчний тип даних Cuisine, щоб представити ці ресторани такими двома випадками: Korean або Turkish.
Фільмів безліч, тож щоб звузити вибір, партнер також називає свій улюблений жанр.
Визначте алгебраїчний тип даних Genre, щоб представити такі випадки жанрів: Crime, Horror, Romance або Thriller.
Як уже згадувалося, партнер придумав пʼять можливих занять: гра в настільну гру, відпочинок, перегляд фільму, похід до ресторану та прогулянка.
Визначте алгебраїчний тип даних Activity, щоб представити ці типи занять:
BoardGame: без повʼязаних даних.Chill: без повʼязаних даних.Movie: має свій Genre як повʼязані дані.Restaurant: має свою Cuisine як повʼязані дані.Walk: має Int, що представляє кількість кілометрів для прогулянки, як повʼязані дані.Нарешті ми готові оцінити ідеї партнера. Ось як ми ставимося до ідей партнера:
Реалізуйте функцію з назвою rateActivity, яка приймає значення Activity і повертає Approval відповідно до наведених вище вподобань.
Наприклад:
rateActivity (Restaurant Turkish)
-- -> Maybe