Здравствуйте, Mamut, Вы писали:
A>>A>>read_order_from_db :: OrderId -> Either NewOrder ProcessedOrder
A>>
A>>И теперь для того, чтобы вызвать change_order_amount, требуется паттерн-матчинг для определения "подтипа".
M>Ну то есть компилятор нам все равно нам особо-то не помогает. В общем, не нужно ©
Почему не помогает? Он же не дает передать в change_order_amount неопределенный Order.
M>Потому что дальше все становится хуже, процитирую отсюда http://rsdn.ru/forum/philosophy/5944219Автор: Mamut
Дата: 04.02.15
M>M>Только вот незадача-то. Объект у нас одного типа — заказ.
M>И дальше над ним может идти очень длинная последовательность действий. Где в одном действии ему надо быть уже отосланным, в другом — неотосланным, в пятом — отосланным, но неоплаченным, в десятом — просто не иметь статуса "fraud". Как предлагаешь поступать? Писать стопятьсот типов на каждый чих и комбинацию, а потом стопятьсот if'ов, инициализаторов и кастований из одного в другое?
M>)
Думаю, что выражать через типы имеет смысл только достаточно стабильную часть логики, т.к. изменение типов может быть болезненной процедурой и затрагивать кучу мест в проекте.
Ограничение "нельзя менять amount у processed order" выглядит стабильным.
Если amount меняется только в одном месте, то, наверно, смысла выражать это правило через типы нет.
Если таких мест 1024, то смысл появляется.
+= Еще один момент: некая функция принимает параметром Order, вызывает другую, та третью и далее по цепочке. Нам нужна гарантия, что эта некая функция не меняет amount, т.к. мы ее вызываем с processed order. Если тип параметра явно указать как ProcessedOrder, то такую гарантию нам даст компилятор, если нет — то остается только просматривать всю цепочку вызовов. Так что вышеуказанные "1024 мест" включают и такие случаи.