开发者

What happens to you if you break the monad laws?

开发者 https://www.devze.com 2023-03-14 08:22 出处:网络
Do the compiler or 开发者_开发技巧the more \"native\" parts of the libraries (IO or functions that have access to black magic and the implementation) make assumptions about these laws? Will breaking t

Do the compiler or 开发者_开发技巧the more "native" parts of the libraries (IO or functions that have access to black magic and the implementation) make assumptions about these laws? Will breaking them cause the impossible to happen?

Or do they just express a programming pattern -- ie, the only person you'll annoy by breaking them are people who use your code and didn't expect you to be so careless?


The monad laws are simply additional rules that instances are expected to follow, beyond what can be expressed in the type system. Insofar as Monad expresses a programming pattern, the laws are part of that pattern. Such laws apply to other type classes as well: Monoid has very similar rules to Monad, and it's generally expected that instances of Eq will follow the rules expected for an equality relation, among other examples.

Because these laws are in some sense "part of" the type class, it should be reasonable for other code to expect they will hold, and act accordingly. Misbehaving instances may thus violate assumptions made by client code's logic, resulting in bugs, the blame for which is properly placed at the instance, not the code using it.

In short, "breaking the monad laws" should generally be read as "writing buggy code".


I'll illustrate this point with an example involving another type class, modified from one given by Daniel Fischer on the haskell-cafe mailing list. It is (hopefully) well known that the standard libraries include some misbehaving instances, namely Eq and Ord for floating point types. The misbehavior occurs, as you might guess, when NaN is involved. Consider the following data structure:

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

Where 0/0 produces a NaN, which violates the assumptions about Ord instances made by Data.Set.Set. Does this Set contain 0?

> member 0 x
True

Yes, of course it does, it's right there in plain sight! Now, we insert a value into the Set:

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

This Set still contains 0, right? We didn't remove anything, after all.

> member 0 x'
False

...oh. Oh, dear.


The compiler doesn't make any assumptions about the laws, however, if your instance does not obey the laws, it will not behave like a monad -- it will do strange things and otherwise appear to your users to not work correctly (e.g. dropping values, or evaluating things in the wrong order).

Also, refactorings your users might make assuming the monad laws hold will obviously not be sound.


For people working in more "mainstream" languages, this would be like implementing an interface, but doing so incorrectly. For example, imagine you're using a framework that offers an IShape interface, and you implement it. However, your implementation of the draw() method doesn't draw at all, but instead merely instantiates 1000 more instances of your class.

The framework would try to use your IShape and do reasonable things with it, and God knows what would happen. It'd be kind of an interesting train wreck to watch.

If you say you're a Monad, you're "declaring" that you adhere to its contract and laws. Other code will believe your declaration and act accordingly. Since you lied, things will go wrong in unforeseen ways.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号