[英]Why is ListT monad transformer considered buggy - what monad laws it breaks?
[英]What happens to you if you break the monad laws?
编译器或库中更“本机”的部分(IO或能够访问黑魔法和实现的函数)是否对这些定律做出假设? 打破它们会导致不可能发生的事吗?
或者他们只是表达一种编程模式 - 也就是说,你唯一能够惹恼他们的人就是那些使用你的代码并且不希望你如此粗心的人?
monad法则只是实例预期遵循的附加规则,超出了类型系统中可以表达的范围。 就Monad
表达编程模式而言,法律是该模式的一部分 。 此类法律也适用于其他类型类: Monoid
与Monad
具有非常相似的规则,并且通常期望Eq
实例将遵循平等关系所期望的规则,以及其他示例。
因为这些定律在某种意义上是“类型”的一部分,所以其他代码期望它们能够持有并且相应地采取行动应该是合理的。 因此,行为不当的实例可能会违反客户端代码逻辑所做的假设,从而导致错误,其中的错误适当地放在实例上,而不是使用它的代码。
简而言之,“打破monad法则”通常应该被理解为“编写错误代码”。
我将通过一个涉及另一个类型类的示例来说明这一点,该类由Daniel Fischer在haskell-cafe邮件列表中给出的类修改。 (希望)众所周知,标准库包括一些行为不当的实例,即浮点类型的Eq
和Ord
。 正如您所猜测的那样,当涉及NaN时,会发生不当行为。 考虑以下数据结构:
> let x = fromList [0, -1, 0/0, -5, -6, -3] :: Set Float
其中0/0
产生NaN,这违反了Data.Set.Set
对Ord
实例的假设。 这个Set
是否包含0
?
> member 0 x
True
是的,当然它确实如此,它就在那里! 现在,我们在Set
插入一个值:
> let x' = insert (0/0) x
这个Set
还包含0
,对吗? 毕竟,我们没有删除任何东西。
> member 0 x'
False
...... 哦 噢亲爱的。
编译器不对法律作出任何假设,但是,如果您的实例不遵守法律,它将不会像monad一样 - 它会做一些奇怪的事情,否则会让您的用户看起来不能正常工作(例如掉线)价值观,或以错误的顺序评估事物)。
此外,假设monad法则保持不变,用户可能会进行重构。
对于使用更多“主流”语言的人来说,这就像实现一个接口,但这样做不正确。 例如,假设您正在使用提供IShape接口的框架,并实现它。 但是,您的draw()方法的实现根本不会绘制,而只是实例化您的类的1000多个实例。
该框架将尝试使用您的IShape并使用它做合理的事情,并且上帝知道会发生什么。 这是一个有趣的火车残骸值得关注。
如果你说你是一个Monad,你就是“声明”你遵守其合同和法律。 其他代码将相信您的声明并采取相应行动。 既然你撒谎,事情会以不可预见的方式出错。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.