J>Не очень понятно, что должно было продемонстрировать твое решение в лоб, кроме того, что задачу можно решить в лоб
Если бы кто-то из апологетов типизации все же решился и показал мастер-класс, можно было бы сравнить, насколько легко переходить из шага 1 в шаг 2, потом в шаг 3 в коде с типами.
Именно поэтому:
Для спортивности: не смотрите в следующий шаг, пока не реализован первый шаг.
Я начал писать, но понял, что можно сделать красивее, но когда начал переписывать, увидел, что можно ещё красивее сделать... Ну и отвлёкся на поработать.
Там конструкция примерно такая выходит
template<class PT> struct match_phantom;
template<class N, class P> struct match_phantom<phantom_type<N,P>> { typedef N n_type; typedef P p_type; };
template<class PT> using phantom<PT> = match_phantom<PT>::p_type;
template<class PT> using net<PT> = match_phantom<PT>::n_type;
template<class PT, class P1> using update_phantom = phantom_type<net<PT>, P1>;
template<class Final> struct applicator
{
template<class PT> using asserted_and_transformed =
enabled_if<
Final::precondition<phantom<PT>>::value, // выковыриваем признаки и проверяем предусловие
update_phantom<PT, Final::transform<PT>> // получаем новые признаки и пришиваем к типу
>;
static template<class PT> auto action(PT pt) -> asserted_and_transformed<PT>
{ return Final::work(pt.value); }
};
struct IdentityFunctor : application<SomeFunctor>
{
template<class Phantom> using precondition = mpl_bool<true>;
template<class Phantom> using transform = Phantom;
static Good work(Good value) { return value; }
};
// признаки, которые нам нужны на первом шаге - пока что свалю в кучуstruct just_started
{
static bool is_paid = false;
static bool is_sent = false;
static bool is_increased = false;
static bool is_checked = true;
};
struct Start : applicator<Start> // прикрутим сюда функтор через CRTP
{
// внутренниеtemplate<class P> using precondition = is_same<P,void>; // для затравкиtemplate<class P> using transform = just_started; // начинаем с вот таких признаков - создаём вот такой фантомstatic Good work(Good value) { return value; } // функция, которую будем лифтить; по умолчанию, id-функцию можно взять из коробки, из applicator.
};
struct Send : applicator<Send>
{
template<class P> using precondition = mpl_bool<P::is_paid && P::is_checked>; // тупой предикат: взять булеву константу из признаковtemplate<class P> struct transform : P { static bool is_sent = true; }; // по-простому, сокрытием имён ввели новое значение
};
struct Increase : application<Increase>
{
template<class P> using precondition = mpl_bool<!P::is_sent>;
template<class P> struct transform : P
{
is_checked = !P::is_sent;
is_increased = true;
};
static Good work(Good value) { return value+1; }
};
Что-то в таком ключе.
Дальше — в зависимости от диалекта. На 98 плюсах будет много слов, на 11 — мало, на 14 — совсем мало.
Как видишь, тут и наглядность не страдает, и кастомизабельность — как следствие — достаточно высокая.
И несложно растащить функции (XXX::work) и метафункции (XXX::precondition, XXX::transform)
Возможно, что в бусте уже всё придумано за нас. А если не придумано, допилю и выложу в продакшен
Здравствуйте, Mamut, Вы писали:
J>>Не очень понятно, что должно было продемонстрировать твое решение в лоб, кроме того, что задачу можно решить в лоб
M>Если бы кто-то из апологетов типизации все же решился и показал мастер-класс, можно было бы сравнить, насколько легко переходить из шага 1 в шаг 2, потом в шаг 3 в коде с типами.
Еще раз — типы вводятся не для легкости, а для корректности.
Единственное, что облегчают типы — это проверку корректности, потому что ею автоматически занимается компилятор, а не программер с лупой по коду ползает.
Про то, что их легче писать, никто не говорил (ну, я не говорил; за всех не скажу).
M>Но пока что никто не рискнул
Я тоже легко объясню, почему — у меня рабочий день, семья и все такое, я ж не могу только для тебя код писать
На самом деле, у меня давно уже свой девайс был, еще когда я начал изучать зависимые типы (несколько лет назад, когда тут они активно обсуждались при участии lomeo и thesz) и пытался их сэмулировать на С++ (по сути, тут у нас зависимые типы и проявятся).
Так что надо посмотреть, в каком виде можно прикрутить мой девайс к твоей формулировке. И заодно перевести его на С++11
Но я бы хотел посмотреть и на решения на Хаскелле от настоящих сварщиков.
Вижу пачку предикатов на (Order, NewAmount), возвращающих (ok | (Error, Reason)).
Как вариант, можно было, например, сделать, чтобы вместо ok возвращался "помеченный" Order:
data CanUpdateAmountOrder = CanUpdateAmountOrder Order NewAmount
can_update_amount :: (Order, NewAmount) => Either (CanUpdateAmountOrder Order NewAmount) (Error, Reason)
can_update_amount = ...
Далее поменять update_amount, чтобы принимал параметром этот CanUpdateAmountOrder, тем самым заставляя проверять этот предикат везде, где update_amount вызывается.
Во всех функциях, имеющих смысл только для заказов, у которых можно менять amount также меняем тип параметра.
В идеале хотелось бы, чтобы можно было "помечать" тип произвольной комбинацией аттрибутов и чтобы можно было сказать компилятору, что в функцию foo можно передавать только Order, помеченный аттрибутами A,B и C, а в функцию bar — помеченный C и D, так что если у нас есть Order, помеченный A, B, C и D, то его можно передать в обе функции и т.п. Не знаю, можно ли такой сделать на Хаскеле или C++. Зависимыми типами и прочими liquid types пахнет... )
Здравствуйте, artelk, Вы писали:
A>В идеале хотелось бы, чтобы можно было "помечать" тип произвольной комбинацией аттрибутов и чтобы можно было сказать компилятору, что в функцию foo можно передавать только Order, помеченный аттрибутами A,B и C, а в функцию bar — помеченный C и D, так что если у нас есть Order, помеченный A, B, C и D, то его можно передать в обе функции и т.п. Не знаю, можно ли такой сделать на Хаскеле или C++. Зависимыми типами и прочими liquid types пахнет... )
Основная проблема с проверкой условия "увеличивать можно на max(фиксированная сумма1, процент1 от оригинальной суммы заказа)" в compile-time. Для этого придётся переводить runtime price в compile-time price, соответственно разных воплощений типов-цен будет столько же, сколько и возможных вариантов цен (а соответственно будет много воплощений функции принимающих эти типы).
Если же проверка цены допустима в runtime, и не нужно делать из неё ограничение-тип — то получается намного проще.
Вообще, всё зависит от пред/пост-условий требуемой функции, и соответственно мест в которых она используется.
Если в её предусловия входит выполнение всех этих ограничений/условий, то без предварительных проверок её запускать нельзя. И соответственно все эти проверки надо городить в месте каждого вызова (либо удостовериться в их выполнении другими способами) — то в этом случае форсирование этих условий системой типов имеет смысл.
Если же для запуска функции нет необходимости делать проверки, change_amount сама всё что нужно проверяет внутри, и более того её запуск с невыполненными условиями не является ошибкой, а вполне штатным режимом — то пытаться переписать все эти внутренние проверки на типы, не вижу смысла, это никак не отразится на местах вызова этой функции.
разговор шёл именно о предварительных проверках, а не внутренних:
Ты придумал себе какие-то внутренние и внешние проверки В общем, то, о чем я говорил:
какой-то мегастранный подход апологетов типизации к решению задачи. Почему-то несколько раз для них являлось откровением, что все проверки можно и нужно делать не в местах, откуда вызывается change_amount, а внутри самой функции change_amount.
EP>
M>>То есть четвертый пункт — это
M>>
M>>if is_activated(Order) and is_auth_only(Order):
M>> do_capture(Order)
M>>
M>>Еще раз: как именно типы мне помогут?
EP>В таких случаях пытаться встроить контракт/предусловие в систему типов вполне имеет смысл
J>Еще раз — типы вводятся не для легкости, а для корректности. J>Единственное, что облегчают типы — это проверку корректности, потому что ею автоматически занимается компилятор, а не программер с лупой по коду ползает. J>Про то, что их легче писать, никто не говорил (ну, я не говорил; за всех не скажу).
Не очень понятно, что должно было продемонстрировать твое решение в лоб, кроме того, что задачу можно решить в лоб
В этом никто и не сомневался, вообще-то.
Да, никто не сомневался. Я написал это за 10 минут, на работе. Про типы мне прожужживают уши уже который день и которое сообщение подряд. Но только сказками и рассказами:
Если ты когда-нибудь собирал мозаичные пазлы, то должен был заметить, что различная форма фрагментов рисунка позволяет избежать большинства ошибок и резко ускорить выполнение задачи. Типы в любой логике выполняют примерно туже самую роль.
Они решают задачу бана неправильного кода, где правильность закодирована в определении. У тебя такого бана нету. Можно проверить is_forbidden и тут же дернуть update_amount, и компилятор и не почешется на эту тему, и останется только уповать на тесты.
как можно больше логики кодировать в типах и проверять компилятором. Чем меньше твой язык позволяет выразить типами, тем меньше у тебя ошибок с типами и тем больше ошибок "в логике", это естественно.
Для типов есть легковесная верификация, в случае их отсутствия не все так радужно. Она не перестает быть логикой, она представляется в форме, которая хорошо подходит для автоматической проверки.
Поможет тем, что вы можете делать описание чего-то корректным по построению, например. Т.е. сделать нежелательное состояние непредставимым в виде значения.
Мой пример тривиален, но можно ведь придумать типы и поинтереснее
Вот тут как раз и поможет компилятор — как раз с ad-hoc изменениями требований.
А если ты новое требование закодируешь в типе, то за тем, что ты посетил все 1024 места, проследит компилятор, и он просто не скомпилирует твою программу, пока ты не разберешься со всеми 1024 местами, причем пока не разберешься так, что компилятор будет удовлетворен.
Собственно, в этом весь смысл.
Типы не делают программирование легче и короче, они делают его надежнее и безопаснее.
Стопятьсот сообщений о том, как с типами все зашибись. И никто не осилил простейшей задачи, как раз теми самыми ad-hoc требованиями, о которых презентация, на которую ты скинул ссылку.
Но зато сказок о том, как все прекрасно — ну вот они, выше крыши, в один экран не помещаются.
ты на пару с AlexRk рассказываете сказки про то, как все будет хорошо с обработкой заказа на словах, хотя вот она задача, перед глазами. Покажите не сказками про белого бычка, а реальным кодом.
Это, блин, простейшая бизнес-задача. В которой все ваши рассказы про типы должны просто засиять всеми красками. Где?!
, но без продолжения (но он объяснил, почему).
К>Я начал писать, но понял, что можно сделать красивее, но когда начал переписывать, увидел, что можно ещё красивее сделать... Ну и отвлёкся на поработать.
Это знакомо
К>Как видишь, тут и наглядность не страдает, и кастомизабельность — как следствие — достаточно высокая.
Ээээ, что? Я, конечно, дааавненько на C++ не смотрел, но разобраться во всех этих шаблонах и зависимостях для меня проблема. Скажем, я тут вообще не понимаю: и что же дальше
По-моему, чтобы такое написать, надо быть семи пядей во лбу
К>И несложно растащить функции (XXX::work) и метафункции (XXX::precondition, XXX::transform)
Я за 10 минут растащил все это без шаблонов
К>Возможно, что в бусте уже всё придумано за нас. А если не придумано, допилю и выложу в продакшен
Да, хотел бы посмотреть на результат Надо не забывать, из всего этого еще внятные ошибки хотелось бы возвращать
M>>Ну и потому что проблемы типов обычно — мизерная часть собственно проблем в коде. У нас в команде вот за год появился первый тикет, который напрямую связан с ошибкой типов. Все остальные проблемы — это логика.
DM>Ну вот сторонники продвинутых (или хотя бы приличных) систем типов как раз и ратуют за смещение этой границы, чтобы как можно больше логики кодировать в типах и проверять компилятором.
M>>Действительно, ведь раз логика закодирована типами, она перестает быть логикой, ага, и никогда не может быть неверной.
DM>Зачем клоуна строишь? Ничего подобного я не говорил и не имел в виду.
K>>>Проверки типов.
M>>Которая поможет мне с логическими ошибками... как?
K>Так, что некоторые классы ваших логических ошибок будут приводить к ошибкам компиляции.
DM>Я не говорю, что абсолютно все проблемы выявляются любой системой статических типов. Лишь некоторые. И чем выразительней эта система и чем удачнее применяется, тем больше проблем выявляется при компиляции.
EP>Пытаться же запихнуть всю-всю логику в типы — контрпродуктивно, само собой нужен баланс. Как уже неоднократно отмечали выше — типы помогают обнаруживать только некоторые классы ошибок.
EP>Неплохим примером является кодирование единиц измерения и размерности в тип. Например Mars Climate Orbiter распался в атмосфере Марса из-за того, что разные модули по ошибке использовали разные единицы измерения.
M>как это все прекрасно проверится при компиляции и т.п.
Предусловие требующее нахождение параметра функции в одном из состояний из небольшого множества — действительно можно задать в системе типов, причём таким образом что вызывающая сторона не сможет это требование проигнорировать, и в той теме приводили примеры.
M>Вот я не выдержал и свел воедино одну достаточно простую задачу.
Ты же понимаешь что из истинности утверждения "логику моего опердня не имеет смысл кодировать в типах", не следует ложность утверждения "при грамотном использовании системы типов, некоторые классы логических ошибок будут приводить к ошибкам компиляции"
Мол, "шах и мат атеистыстатическая типизация!"
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, Mamut, Вы писали:
M>>Ну, ту просто в соседней теме мне все уши прожужжали, как надо всю логику класть в типы,
EP>Не всю, а как можно больше:
M>>как это все прекрасно проверится при компиляции и т.п.
EP>Предусловие требующее нахождение параметра функции в одном из состояний из небольшого множества — действительно можно задать в системе типов, причём таким образом что вызывающая сторона не сможет это требование проигнорировать, и в той теме приводили примеры.
Которые тут же сыпались при простейших вопросах типа «что будет, если ввести хоть одно доп. условие?».
M>>Вот я не выдержал и свел воедино одну достаточно простую задачу.
EP>Ты же понимаешь что из истинности утверждения "логику моего опердня не имеет смысл кодировать в типах", не следует ложность утверждения "при грамотном использовании системы типов, некоторые классы логических ошибок будут приводить к ошибкам компиляции"
Я пока понимаю, что апологеты типов не могут ничего рассказать и показать, кроме сказок о том, как все с типами будет круто, и «нужно как можно больше логики кодировать на типах».
Любые попытки свести разговор к конкретным примерам заканчиваются лишь очередными сказками или «не, ну оно позволяет не сравнивать километры с килограммами». Это все? Не слишком много для «как можно больше логики кодируй в типах» и прочей «мозаики». Почему-то вся «логика» сводится к «не вызвать функцию F с параметром Y, когда нужен параметр Z»
Тебе не нравится опердень? Странно. jazzer привел ссылку на презентацию из банка, где опердени — это, по сути, единственное, чем они занимаются. Более того, задача, которую я привел, тоже из банка. Но ни тебе ни IT
разговор шёл именно о предварительных проверках, а не внутренних: M>Ты придумал себе какие-то внутренние и внешние проверки В общем, то, о чем я говорил: M>
M>какой-то мегастранный подход апологетов типизации к решению задачи. Почему-то несколько раз для них являлось откровением, что все проверки можно и нужно делать не в местах, откуда вызывается change_amount, а внутри самой функции change_amount.
M>- Есть заказ.
M>- Пока заказ не помечен, как отправленный, можно уменьшать и увеличивать сумму заказа
M> ...
M>
это можно трактовать как "можно уменьшать и увеличивать сумму заказа" — это функция change_amount, у которой есть предусловие "заказ не помечен как отправленный", которая безусловно изменяет сумму. Тебе как раз и показывали примеры форсирующие это предусловие в compile-time:
ARK> function SendOrder(order: UnsentOrder): SentOrder is
ARK> ...
ARK> end;
ARK> function ChangeOrderSum(order: UnsentOrder, newSum: Money): UnsentOrder is
ARK> // эту функцию нельзя вызвать для заказа, у которого Sent равно true!
ARK> ...
ARK> end;
ARK>
EP>>
M>>>То есть четвертый пункт — это
M>>>
M>>>if is_activated(Order) and is_auth_only(Order):
M>>> do_capture(Order)
M>>>
M>>>Еще раз: как именно типы мне помогут?
EP>>В таких случаях пытаться встроить контракт/предусловие в систему типов вполне имеет смысл M>Можно увидеть это не на словах, а на деле?
Здравствуйте, Mamut, Вы писали:
M>>>Ну, ту просто в соседней теме мне все уши прожужжали, как надо всю логику класть в типы, EP>>Не всю, а как можно больше: M>Спасибо, я эти все сказки свел воедино тут: http://rsdn.ru/forum/philosophy/5946930.1
И где там говорится что всю логику надо класть в типы?
"как можно больше" != "всю"
M>Которые тут же сыпались при простейших вопросах типа «что будет, если ввести хоть одно доп. условие?».
.
M>>>Вот я не выдержал и свел воедино одну достаточно простую задачу. EP>>Ты же понимаешь что из истинности утверждения "логику моего опердня не имеет смысл кодировать в типах", не следует ложность утверждения "при грамотном использовании системы типов, некоторые классы логических ошибок будут приводить к ошибкам компиляции" M>Я пока понимаю, что апологеты типов не могут ничего рассказать и показать,
Скорее ты не хочешь слышать и видеть.
M>кроме сказок о том, как все с типами будет круто, и «нужно как можно больше логики кодировать на типах».
Не "всё будет круто", а "целые классы ошибок будут ловиться в compile-time".
M>Любые попытки свести разговор к конкретным примерам заканчиваются лишь очередными сказками или «не, ну оно позволяет не сравнивать километры с килограммами». Это все? Не слишком много для «как можно больше логики кодируй в типах» и прочей «мозаики». Почему-то вся «логика» сводится к «не вызвать функцию F с параметром Y, когда нужен параметр Z»
Во-первых, учитывая то что набор типов не фиксирован, а вычисляется на основе "шаблонов", этого не так уж и мало. Например та же размерность физических величин: разделив метры на секунды, мы получим значение нового типа, с размерностью м/c.
А во-вторых, на типах можно задать какие угодно условия, главное чтобы аргументы условий были доступны compile-time. Например "первый и второй параметр должны иметь одинаковый тип", хотя и не говорится какой; или например целая цепочка условий, а-ля ДНФ.
M>Тебе не нравится опердень? Странно. jazzer привел ссылку на презентацию из банка, где опердени — это, по сути, единственное, чем они занимаются. Более того, задача, которую я привел, тоже из банка. Но ни тебе ни IT
эта задача не нравится. Ну что я могу поделать, если ваше чувство прекрасного нарушено этой задачей
Почему это не нравится? Задача как задача
M>Приведите другую задачу. Но только без hello word'ов, а такую, хоть как-то приближенную к реальности.
Например CAD модели заданные в аффинном пространстве. Если и точки и вектора имеют тип vector, то возможно допустить логические ошибки: попытаться просуммировать точки; или например передать результат суммы векторов туда, где по логике ожидается точка; или же сохранить сумму точки и вектора в вектор.
Если же и точки и вектора будут иметь типы Point и Vector соответственно, то подобную логику можно закодировать в сигнатурах операций, и ошибки такого рода будут автоматически находится на этапе компиляции.
Здравствуйте, Mamut, Вы писали:
J>>Еще раз — типы вводятся не для легкости, а для корректности. J>>Единственное, что облегчают типы — это проверку корректности, потому что ею автоматически занимается компилятор, а не программер с лупой по коду ползает. J>>Про то, что их легче писать, никто не говорил (ну, я не говорил; за всех не скажу).
M>
M>Не очень понятно, что должно было продемонстрировать твое решение в лоб, кроме того, что задачу можно решить в лоб
M>В этом никто и не сомневался, вообще-то.
M>Да, никто не сомневался. Я написал это за 10 минут, на работе. Про типы мне прожужживают уши уже который день и которое сообщение подряд. Но только сказками и рассказами:
M>Стопятьсот сообщений о том, как с типами все зашибись.
И стопятьсот сообщений от тебя про белого бычка, тупо игнорирующих все, что тебе говорят (и это сообщение — тоже яркий тому пример: ты тупо проигнорировал мои слова наверху, и так почти со всем).
И потом тебе еще хватает уж не знаю чего заявлять "там много флейма и отсутсвие конструктива".
В зеркало посмотрись сначала.
Пример моментально развалился при простейшем вопросе: у нас этих условий не 2, а 12. Будешь делать order_processed_and_prepaid_and_not_risk_and_amount_raise_allowed_and... ?
EP>Скорее ты не хочешь слышать и видеть.
Я все вижу и слышу. Вас почему-то корежит от вопросов
M>>кроме сказок о том, как все с типами будет круто, и «нужно как можно больше логики кодировать на типах». EP>Не "всё будет круто", а "целые классы ошибок будут ловиться в compile-time".
Я привел простейший пример. Покажи мне, как в нем булет отлавливаться целый класс ошибок.
EP>Во-первых, учитывая то что набор типов не фиксирован, а вычисляется на основе "шаблонов", этого не так уж и мало. Например та же размерность физических величин: разделив метры на секунды, мы получим значение нового типа, с размерностью м/c. EP>А во-вторых, на типах можно задать какие угодно условия, главное чтобы аргументы условий были доступны compile-time. Например "первый и второй параметр должны иметь одинаковый тип", хотя и не говорится какой; или например целая цепочка условий, а-ля ДНФ.
Имя сестра, имя Примеры, брат, примеры. Я про это и говорю: сплошные сказки про белого бычка. Я привел пример простейшей задачи, которая — ой, ты не поверишь — имеет цепочку условий. Где на практике твое крутое решение, вычисляющее на основе шаблонов и т.п.
Ах да, я забыл. «Это простой опердень, мне не нравится»
EP>Почему это не нравится? Задача как задача
Так где же решение, которое бы показало все твои истории про типы?
M>>Приведите другую задачу. Но только без hello word'ов, а такую, хоть как-то приближенную к реальности.
EP>Например CAD модели заданные в аффинном пространстве. Если и точки и вектора имеют тип vector, то возможно допустить логические ошибки: попытаться просуммировать точки; или например передать результат суммы векторов туда, где по логике ожидается точка; или же сохранить сумму точки и вектора в вектор.
Короче, понятно. Все сказки про «целые классы ошибок» и «цепочки условий» и «логику» на практике упираются ровно в одно: как бы не сложить метры с киллограммами. Этот «целый класс ошибок» является очень маленьким классом ошибок.
EP>Вот твой изначальный пример: EP>это можно трактовать как "можно уменьшать и увеличивать сумму заказа" — это функция change_amount, у которой есть предусловие "заказ не помечен как отправленный", которая безусловно изменяет сумму. Тебе как раз и показывали примеры форсирующие это предусловие в compile-time:
Я перенес это «предусловие» внутрь функции change_amount. Что изменилось? Ничего. Все те же «предусловия» надо продолжать проверять прежде, чем произойдет собственно изменение значения. Но почему-то для тебя и остальных апологетов это стало непреодолимым препятствием
M>>Можно увидеть это не на словах, а на деле?
EP>Конечно: EP>
Можно увидеть на деле то, что описано в корневом сообщении этого топика? Я за пять минут написал свое решение. Ни один из апологетов типов не осилил написать это решение — только отмазки, рассказы про то, как все будет хорошо, и наугад вырванные отдельные куски условий с заявлениями «видишь, как все хорошо»?
J>И стопятьсот сообщений от тебя про белого бычка, тупо игнорирующих все, что тебе говорят (и это сообщение — тоже яркий тому пример: ты тупо проигнорировал мои слова наверху, и так почти со всем).
Проигнорорвал какие слова? Давай я приведу твои слова. Ну, например:
Вот тут как раз и поможет компилятор — как раз с ad-hoc изменениями требований.
типы вводятся не для легкости, а для корректности.
J>И потом тебе еще хватает уж не знаю чего заявлять "там много флейма и отсутсвие конструктива". J>В зеркало посмотрись сначала.
Смотрюсь. Каждое утро. И вижу, что от тебя, например, ноль ральных примеров, одни только заявления. Вот, пожалуйста, задача с ad-hoc требованиями. Очень маленькая, на самом деле. Можно увидеть пример того, как (все строго на основе твоих заявлений)
— компилятор помогает с ad-hoc изменениями
— типы помогают возвращать ошибки
— типы помогают проверить корректность
Ну вот без заявлений о том, как все это прекрасно происходит в теории. А вот на реальной задаче, которой, заметь, занимается банк. Ты ведь презентацию из банка про хаскель привел. Ну вот тебе вполне банковская задача
Уважаемый, я вот что скажу. Качественных примеров на типах мы в этом треде вряд ли дождёмся по простой причине: пока что не наработаны методики написания такого кода. Вот, например, когда появилось ООП, то далеко не сразу народ стал активно (а главное — правильно!) его использовать. Нужно подождать. С течением времени появятся новые методики и паттерны, качественная поддержка в компиляторах и IDE, а также опыт разработчиков.
Здравствуйте, Mamut, Вы писали:
M>Пример моментально развалился при простейшем вопросе: у нас этих условий не 2, а 12. Будешь делать order_processed_and_prepaid_and_not_risk_and_amount_raise_allowed_and... ?
order<processed, prepaid, not_risk, amount_rise_allowed>, либо просто order<state>
EP>>Скорее ты не хочешь слышать и видеть. M>Я все вижу и слышу. Вас почему-то корежит от вопросов
От каких?
M>>>кроме сказок о том, как все с типами будет круто, и «нужно как можно больше логики кодировать на типах». EP>>Не "всё будет круто", а "целые классы ошибок будут ловиться в compile-time". M>Я привел простейший пример. Покажи мне, как в нем булет отлавливаться целый класс ошибок.
Например если вместо ордера передадут соединение — целый класс ошибок.
"Целый класс ошибок" не означает "во всех задачах, большинство ошибок"
EP>>Во-первых, учитывая то что набор типов не фиксирован, а вычисляется на основе "шаблонов", этого не так уж и мало. Например та же размерность физических величин: разделив метры на секунды, мы получим значение нового типа, с размерностью м/c. EP>>А во-вторых, на типах можно задать какие угодно условия, главное чтобы аргументы условий были доступны compile-time. Например "первый и второй параметр должны иметь одинаковый тип", хотя и не говорится какой; или например целая цепочка условий, а-ля ДНФ. M>Имя сестра, имя Примеры, брат, примеры. Я про это и говорю: сплошные сказки про белого бычка. Я привел пример простейшей задачи, которая — ой, ты не поверишь — имеет цепочку условий. Где на практике твое крутое решение, вычисляющее на основе шаблонов и т.п.
Придётся повторится: "на типах можно задать какие угодно условия, главное чтобы аргументы условий были доступны compile-time".
M>Ах да, я забыл. «Это простой опердень, мн ене нравится»
Где я говорил что мне не нравится?
EP>>Почему это не нравится? Задача как задача M>Так где же решение, которое бы показало все твои истории про типы?
Какие конкретно "мои истории про типы"?
Давай уж, приводи цитаты.
M>Короче, понятно. Все сказки про «целые классы ошибок» и «цепочки условий» и «логику» на практике упираются ровно в одно: как бы не сложить метры с киллограммами. Этот «целый класс ошибок» является очень маленьким классом ошибок.
Так ты определились, либо "целые классы ошибок" это сказки, либо нет и тебе просто не нравится количество этих классов, а конкретно их концентрация в одном примере из твоего опердня