Что случится с тобой, если ты нарушишь законы монады?

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

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

3 ответов


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

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


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

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

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


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

> 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

...о. О, боже.


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

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

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