Что будет с вами, если вы нарушите законы монады? - PullRequest
37 голосов
/ 19 июня 2011

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

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

Ответы [ 3 ]

58 голосов
/ 19 июня 2011

Законы монады - это просто дополнительные правила, которым должны следовать экземпляры, помимо того, что может быть выражено в системе типов.Поскольку 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

... о .Ох, дорогой.

26 голосов
/ 19 июня 2011

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

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

11 голосов
/ 22 июня 2011

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

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

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

...