Только вот вы эти проблемы тоже не решаете.
1) Вы передаёте в on-result-fn контекст, каким он был до выполнения кинувшей exception функции. Ни что это за функция, ни какой был exception — вы не узнаёте. Более того, вы даже не знаете, on-result-fn вызывается после успешного выполнения или из-за ошибки, если не впихнёте это в context.
Если вам достаточно такого странного — можно сделать свой instance монады и доопределить bind. Если нет, вам тоже придется придумывать тот же самый велосипед.
2) А вам что делать? У вас нет «продолжить отсюда». Вы можете только стартовать все операции с начала, и пропускать внутри те, которые уже были выполнены — проверяя внутри это контест. Так и я могу. Или же как-то допилить ваш велосипед, дополнив его еще парой костылей.
К тому же мы сделали rollback согласно пункту 1, то операции в любом случае нужно выполнять опять.
Может быть, решает, да. Но с моей точки зрения вы просто переизобрели велосипед — монаду Either.
> Элементарное действие принимает контекст единственным параметром.
Не вижу сложностей. Просто не делайте других параметров. И кстати, как вы тогда будете реализовывать действие «вернуть первые N записей»? Требовать, чтобы N было в вашем контексте под каким-то именем? Согласитесь, это же некрасиво. Особенно если это действие — первое в списке из нескольких. Потому что более никому ненужный параметр N так в контексте и останется.
> Результат нужно возвращать после применения элементарных действий над текущим контекстом.
Извиняюсь, не заметил, что промежуточные значения вы просто кладете в контекст. (Впрочем, until-first-error так и так возвращает updated-context, а не результат.) Только вот это порождает сразу несколько проблем. Как минимум, ломается изоляция — последующие функции видят результат всех предыдущих, если его явно не удалили из контекста. А удалять — значит это вы рассчитываете, что после функции a будет в цепочке функций всегда b, которая удалит результат a из контекста. Но тогда эти две функции разумно объединить.
>Является ли контекстное программирование заменой монадного программирование и решает ли он те же задачи, что и монады?
Не является. И не решает. Но все костыли вашего контекстного программирования заменяются использованием монады Either, даже не требуя глубокого понимания «что такое монады».
На самом деле большинство людей использует монады задолго до того, как слышит слово монада. Те же самые Maybe (т.е. вернуть значение или ничего) и Either (вернуть значение или ошибку) спокойно используются без каких-либо знаний о монадах.
И как раз-таки ваше «элементарное действие» это просто функция, принимающая дополнительным параметром Context и возвращающая Either Error Context. Даже монады знать не надо, чтобы так написать.
А потом, когда вы хотите скомбинировать несколько «действий» в одно, которое бы вернуло итоговый результат или первую ошибку — вы можете написать комбинирующую функцию вручную, а можете воспользоваться тем, что Either это монада и значит её можно комбинировать с другими Either — как раз так, как вам надо. И о монадах можете продолжать не знать ничего, кроме как что они комбинируются между собой.
Плюс заметьте, что мы совсем даже не использовали State — потому что возвращаем новый контекст в результате. А что если мы хотим вернуть какой-то осмысленный результат? Конечно, вы можете возвращать пару из Context и результата. Но как потом скомбинировать это действие с другим действием, которое принимает как аргументы ваш результат и Context(не как одну пару)? Ещё больше костылей. Или же вы прочитаете про монаду State и используете её.
TL DR: вы уже написали код с монадой Either, но не знаете об этом — и поэтому не пользуетесь преимуществами монад.
Конкретно в данном случае — вы используете монаду Either для ошибок и State для контекста. Чистая функция, которая может вернуть результат или ошибку — пишется именно с помощью Either. А until-first-error — это bind для Either (точнее, часть с матчингом) плюс костыль — обработка списка, которая решается функцией fold.
Проще говоря, вы не знаете, что монады уже умеют всё это делать, и поэтому городите велосипеды.
Плюс, если посмотреть на типичные монады Reader — Writer — State — они предназначены для ситуаций только читать(конфиги) — только писать(логи) — читать+писать(контекст). И чтобы использовать любую из них, достаточно завернуть функцию в монаду. А вам, чтобы сделать Reader+State, например, придется либо оставить конфиги изменяемыми и сделать их частью контекста(а потом искать ошибку, когда кто-то по ошибке их поменяет), либо городить еще больше велосипедов.
Еще одно очень большое допущение — что сервера всё время исправно работают, и логи исправно создаются.
Если бы не команда QUERY, имело бы смысл делать препроцессинг, считать частичные суммы и прочие программистские оптимизации. Но с ней (и учитывая, что 1 секунду будут измерять по ней) смысл имеет только как-то похранить данные. А для этого имхо лучше воспользоваться стандартным решением под данные нужды — упомянутыми выше RouR Time-Series Database или любой другой БД, если о них пишущий не знает.
Во-первых, требуется обосновать, зачем собираются те или иные данные и почему нельзя собирать меньше. Но тут могут и отбрехаться ролью агрегатора.
Во-вторых, как вы упомянули, необходима возможность данные удалить. Из блокчейна. Одним из ключевых свойств которого является отсутствие возможности изменять и удалять данные.
Остаётся всё тот же вопрос — куда пихать все произведенные чипы. Он есть и при капитализме, и при социализме (если потребность N чипов, что делать с остальными).
Ту же конкуренцию можно иметь между КБ, и в СССР это было, например в авиации точно.
А вот необходимость очень большого рынка для снижения себестоимости никуда не деть.
На самом деле для firefox у вас удачно совпало, что дефолтный размер массива равен двум. Видимо, там используется mergesort с делением на степени двойки или что-то подобное. Попробуйте size=24 например. Кстати, это наименьший размер, на котором используется этот алгоритм, 23 еще другой)
1) Вы передаёте в on-result-fn контекст, каким он был до выполнения кинувшей exception функции. Ни что это за функция, ни какой был exception — вы не узнаёте. Более того, вы даже не знаете, on-result-fn вызывается после успешного выполнения или из-за ошибки, если не впихнёте это в context.
Если вам достаточно такого странного — можно сделать свой instance монады и доопределить bind. Если нет, вам тоже придется придумывать тот же самый велосипед.
2) А вам что делать? У вас нет «продолжить отсюда». Вы можете только стартовать все операции с начала, и пропускать внутри те, которые уже были выполнены — проверяя внутри это контест. Так и я могу. Или же как-то допилить ваш велосипед, дополнив его еще парой костылей.
К тому же мы сделали rollback согласно пункту 1, то операции в любом случае нужно выполнять опять.
> Элементарное действие принимает контекст единственным параметром.
Не вижу сложностей. Просто не делайте других параметров. И кстати, как вы тогда будете реализовывать действие «вернуть первые N записей»? Требовать, чтобы N было в вашем контексте под каким-то именем? Согласитесь, это же некрасиво. Особенно если это действие — первое в списке из нескольких. Потому что более никому ненужный параметр N так в контексте и останется.
> Результат нужно возвращать после применения элементарных действий над текущим контекстом.
Извиняюсь, не заметил, что промежуточные значения вы просто кладете в контекст. (Впрочем, until-first-error так и так возвращает updated-context, а не результат.) Только вот это порождает сразу несколько проблем. Как минимум, ломается изоляция — последующие функции видят результат всех предыдущих, если его явно не удалили из контекста. А удалять — значит это вы рассчитываете, что после функции a будет в цепочке функций всегда b, которая удалит результат a из контекста. Но тогда эти две функции разумно объединить.
>Является ли контекстное программирование заменой монадного программирование и решает ли он те же задачи, что и монады?
Не является. И не решает. Но все костыли вашего контекстного программирования заменяются использованием монады Either, даже не требуя глубокого понимания «что такое монады».
И как раз-таки ваше «элементарное действие» это просто функция, принимающая дополнительным параметром Context и возвращающая Either Error Context. Даже монады знать не надо, чтобы так написать.
А потом, когда вы хотите скомбинировать несколько «действий» в одно, которое бы вернуло итоговый результат или первую ошибку — вы можете написать комбинирующую функцию вручную, а можете воспользоваться тем, что Either это монада и значит её можно комбинировать с другими Either — как раз так, как вам надо. И о монадах можете продолжать не знать ничего, кроме как что они комбинируются между собой.
Плюс заметьте, что мы совсем даже не использовали State — потому что возвращаем новый контекст в результате. А что если мы хотим вернуть какой-то осмысленный результат? Конечно, вы можете возвращать пару из Context и результата. Но как потом скомбинировать это действие с другим действием, которое принимает как аргументы ваш результат и Context(не как одну пару)? Ещё больше костылей. Или же вы прочитаете про монаду State и используете её.
TL DR: вы уже написали код с монадой Either, но не знаете об этом — и поэтому не пользуетесь преимуществами монад.
Проще говоря, вы не знаете, что монады уже умеют всё это делать, и поэтому городите велосипеды.
Плюс, если посмотреть на типичные монады Reader — Writer — State — они предназначены для ситуаций только читать(конфиги) — только писать(логи) — читать+писать(контекст). И чтобы использовать любую из них, достаточно завернуть функцию в монаду. А вам, чтобы сделать Reader+State, например, придется либо оставить конфиги изменяемыми и сделать их частью контекста(а потом искать ошибку, когда кто-то по ошибке их поменяет), либо городить еще больше велосипедов.
В ФП контекст обеспечивает монада State.
Если бы не команда QUERY, имело бы смысл делать препроцессинг, считать частичные суммы и прочие программистские оптимизации. Но с ней (и учитывая, что 1 секунду будут измерять по ней) смысл имеет только как-то похранить данные. А для этого имхо лучше воспользоваться стандартным решением под данные нужды — упомянутыми выше RouR Time-Series Database или любой другой БД, если о них пишущий не знает.
P.S. Pyhon поправьте))
Во-вторых, как вы упомянули, необходима возможность данные удалить. Из блокчейна. Одним из ключевых свойств которого является отсутствие возможности изменять и удалять данные.
Ту же конкуренцию можно иметь между КБ, и в СССР это было, например в авиации точно.
А вот необходимость очень большого рынка для снижения себестоимости никуда не деть.