Раздел 21 · Haskell

Алгебраические типы и моделирование домена

middle~55 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Алгебраические типы и моделирование домена

Типы это конструктор, а не клетка. В этом уроке: 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-коуча.

Оплата пока не подключена: премиум и курсы открываются промокодом.