Алгебраические типы и моделирование домена
Типы это конструктор, а не клетка. В этом уроке: data, newtype и type, records, Maybe и Either. А дальше главный приём всего раздела: спроектировать тип так, чтобы невозможное состояние нельзя было даже собрать, и понять, почему newtype без скрытого конструктора это просто имя, а имя это не типобезопасность.
Идея
Пять уроков подряд все данные были числами, строками и списками. Но домен, ради которого пишут программы, состоит не из них: он состоит из заказов, имейлов, статусов доставки и банковских счетов. Кодировать их приходилось примитивами: статус строкой "paid", деньги числом, имейл строкой. Каждое такое кодирование это обещание, которое живёт только в голове: в этой строке всегда валидный адрес, это число не бывает отрицательным, статусов ровно четыре. Компилятор обещаний не читает. Значит, и не проверяет: опечатка в "payed" доедет до прода молча.
Сегодня появляется data, способ объявлять собственные типы. Устроен он как алгебра с двумя операциями:
data Shape
= Circle Double
| Rect Double Double
- Сумма: значение
Shapeэто ИЛИ круг, ИЛИ прямоугольник. - Произведение: внутри
Rectлежат И ширина, И высота.
Отсюда и название: алгебраические типы данных. Алгебра тут не метафора, она буквально считается. У Bool два жителя: True и False. У пары (Bool, Bool) четыре: два умножить на два. У типа data Answer = Yes | No | Unknown три. Сумма складывает, произведение умножает.
Зачем это считать? Затем, что проектирование типа это подгонка числа представимых состояний под число валидных. Каждый лишний житель типа это состояние, в которое программа способна попасть, хотя не должна: баг, терпеливо ждущий рантайма. Идеальный тип представляет валидные состояния домена и ни одного больше.
Алгебра задаёт форму данных, но не все правила домена выражаются формой: имейл содержит собаку, возраст от 13 до 120, остаток не уходит в минус. Для таких инвариантов есть второй инструмент: спрятать конструктор за границу модуля и пропускать значения только через проверяющую функцию. Форма через data, инварианты через границу модуля. Вместе они дают главный слоган урока: невозможные состояния невыразимы. По влиянию на твой код на любом языке, не только на Haskell, это самый важный урок раздела.
премиум-урок
Продолжение в премиуме: 1 200 ₽ в месяц или 10 000 ₽ в год. Вместе с ним серверные проверки задач и школьные токены AI-коуча.
Оплата пока не подключена: премиум и курсы открываются промокодом.