Подтвердить что ты не робот

Что произойдет с вами, если вы нарушите законы монады?

Сделайте компилятор или более "родные" части библиотек (IO или функции, которые имеют доступ к черной магии и реализации) делают предположения об этих законах? Нарушение их приведет к невозможному?

Или они просто выражают шаблон программирования - т.е. единственный человек, которого вы будете раздражать, нарушая их, - это люди, которые используют ваш код, и не ожидали, что вы так небрежны?

4b9b3361

Ответ 1

Компилятор не делает никаких предположений о законах, однако, если ваш экземпляр не подчиняется законам, он не будет вести себя как монада - он будет делать странные вещи и в противном случае будет казаться, что ваши пользователи не работают правильно (например, сброс значений или оценка вещей в неправильном порядке).

Кроме того, рефакторинг, который могут сделать ваши пользователи, считая, что удержание монадов удержания, очевидно, не будет звуковым.

Ответ 2

Законы монады - это просто дополнительные правила, за которыми, как ожидается, будут следовать экземпляры, помимо того, что может быть выражено в системе типов. Поскольку Monad выражает шаблон программирования, законы являются частью этого шаблона. Такие законы применимы и к другим типам классов: Monoid имеет очень похожие правила для Monad, и обычно ожидалось, что примеры Eq будут следовать правилам, ожидаемым для отношения равенства, среди других примеров.

Поскольку эти законы в некотором смысле являются "частью" класса типа, для другого кода должно быть разумным ожидать, что они будут удерживаться и действовать соответствующим образом. Таким образом, несовместимые экземпляры могут нарушать предположения, сделанные логикой клиентского кода, что приводит к ошибкам, вину за которые правильно помещают в экземпляр, а не код, использующий его.

Короче говоря, "нарушение законов монады" обычно следует читать как "писать багги-код".


Я проиллюстрирую этот момент примером, включающим другой тип класса, измененный от одного, заданного Даниэлем Фишером в списке рассылки haskell-cafe. Хорошо известно, что стандартные библиотеки включают в себя некоторые ошибочные экземпляры, а именно Eq и Ord для типов с плавающей запятой. Неправильное поведение происходит, как вы могли догадаться, когда участвует NaN. Рассмотрим следующую структуру данных:

> let x = fromList  [0, -1, 0/0, -5, -6, -3] :: Set Float

Где 0/0 создает NaN, что нарушает предположения о Ord экземплярах, сделанных Data.Set.Set. Этот Set содержит 0?

> member 0 x
True

Да, конечно, так оно и есть прямо на виду! Теперь мы вставляем значение в Set:

> let x' = insert (0/0) x

Этот Set по-прежнему содержит 0, правильно? В конце концов, мы ничего не удаляли.

> member 0 x'
False

... о. О, дорогая.

Ответ 3

Для людей, работающих на более "основных" языках, это будет похоже на реализацию интерфейса, но это делается неправильно. Например, представьте, что вы используете фреймворк, который предлагает интерфейс IShape, и вы его реализуете. Однако ваша реализация метода draw() вообще не рисуется, а вместо этого просто создает экземпляр еще 1000 экземпляров вашего класса.

Структура попытается использовать ваш IShape и делать с ним разумные вещи, и Бог знает, что произойдет. Было бы любопытно наблюдать за крутой поездкой.

Если вы говорите, что вы Монада, вы "заявляете", что придерживаетесь его контракта и законов. Другой код будет считать вашу декларацию и действовать соответственно. Поскольку вы солгали, все пойдет не так непредвиденным образом.