如果你打破monad法则,你会怎么样?

时间:2011-06-18 23:57:02

标签: haskell compiler-construction semantics monads

编译器或库中更“原生”的部分(IO或能够访问黑魔法和实现的功能)是否对这些法律做出假设?破坏它们会导致不可能发生吗?

或者他们只是表达了一种编程模式 - 也就是说,你唯一能够惹恼他们的人就是那些使用你的代码并且不希望你这么粗心的人?

3 个答案:

答案 0 :(得分:58)

monad法则只是实例预期遵循的附加规则,超出了类型系统中可以表达的范围。在Monad表达编程模式的情况下,法则 该模式的一部分。此类法律也适用于其他类型类:MonoidMonad具有非常相似的规则,并且通常期望Eq的实例将遵循预期的等式关系规则,以及其他类型实例

因为这些法律在某种意义上是“类型”的一部分,所以其他代码期望它们能够持有并且相应地采取行动应该是合理的。因此,行为不当的实例可能会违反客户端代码逻辑所做出的假设,从而导致错误,错误归咎于实例,而不是使用它的代码。

简而言之,“打破monad法则”通常应理解为“编写错误代码”。


我将通过一个涉及另一个类型类的示例来说明这一点,该类由Daniel Fischer在haskell-cafe邮件列表中给出的类修改。 (希望)众所周知,标准库包含一些行为不当的实例,即浮点类型的EqOrd。正如您所猜测的那样,当涉及NaN时,会发生不当行为。请考虑以下数据结构:

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

0/0生成NaN的地方,违反了OrdData.Set.Set个实例的假设。这个Set是否包含0

> member 0 x
True

是的,当然确实如此,它就在眼前!现在,我们在Set

中插入一个值
> let x' = insert (0/0) x

Set仍然包含0,对吗?毕竟,我们没有删除任何东西。

> member 0 x'
False

... 的。哦,亲爱的。

答案 1 :(得分:26)

编译器不会对法律做出任何假设,但是,如果您的实例不遵守法律,它将不会像monad一样 - 它会做一些奇怪的事情,否则会让您的用户无法正常工作(例如,丢弃值,或以错误的顺序评估事物)。

此外,假设monad规则保持不变,用户可能会进行重构。

答案 2 :(得分:11)

对于使用更多“主流”语言的人来说,这就像实现一个界面,但这样做不正确。例如,假设您正在使用提供IShape接口的框架,并实现它。但是,你的draw()方法的实现根本不会绘制,而只是实例化你的类的1000多个实例。

框架会尝试使用你的IShape并用它做合理的事情,天知道会发生什么。这是一个有趣的火车残骸值得关注。

如果你说你是Monad,你就是“声明”你遵守合同和法律。其他代码将相信您的声明并采取相应行动。既然你撒了谎,事情会以不可预见的方式出错。