查看此IO代码:

Prelude> let e = return () :: IO ()
Prelude> e `mappend` e
Prelude> let y = e `mappend` e
Prelude> :t y
y :: IO ()

编辑显然,据我所知,IO具有Monoid实例。

但是,以下内容不应该为了遵循monoid第三定律而对true求值吗?
Prelude> e `mappend` (e `mappend` e) == (e `mappend` e) `mappend` e

<interactive>:14:1: error:
    * No instance for (Eq (IO ())) arising from a use of `=='
    * In the expression:
        e `mappend` (e `mappend` e) == (e `mappend` e) `mappend` e
      In an equation for `it':
          it = e `mappend` (e `mappend` e) == (e `mappend` e) `mappend` e

最佳答案

The third monoid law声明e <> (e <> e) = (e <> e) <> e(对mappend使用易于键入的中缀运算符),而不是e <> (e <> e) == (e <> e) <> e(注意===的区别)。

它表达的是等价的-实际上是表达mappend应该是关联的-并不要求所有Monoid都必须是Eq类型类的实例,而==是此类的。

换句话说,它表达了有关mappend函数行为的高级概念,而不是提供有效的Haskell代码,该代码应特别评估任何东西。

某些Monoid的类型(例如[()])也恰好具有Eq实例。但是有些(例如此处的IO ()实例)没有,这没关系。



另请注意,“IO”没有Monoid实例(无论如何,这是错误的类型)。您正在使用的mappend来自Monoid a => Monoid (IO a)的实例-也就是说,IO配方生成本身就是Monoid的类型。 IOMonoid实例只是在基础Monoid实例上“背负”。

关于haskell - 第三类半定律和IO?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38493804/

10-11 06:23