第三个Monoid法和IO?

时间:2016-07-21 02:18:35

标签: haskell

查看此IO代码:

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

编辑显然,据我所知,IOMonoid个实例。

但是,为了遵守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

1 个答案:

答案 0 :(得分:11)

The third monoid law声明e <> (e <> e) = (e <> e) <> e(使用mappend更容易输入的中缀运算符), e <> (e <> e) == (e <> e) <> e(注意===)。

它表达了一个等价 - 实际上,表达mappend应该是关联的 - 不要求所有Monoid s也必须是Eq类型类的实例,其中{{1}来自。

另一种说法是:它表达了关于==函数行为的高级概念,没有呈现有效的Haskell代码,应该特别评估任何东西。

某些类型mappend s - 例如Monoid - 也碰巧有[()]个实例。但是有些人(比如这里的Eq实例)没有,这没关系。

  

旁注:给IO ()一个IO实例是没有意义的,因为几乎不可能确定某个Eq是否等同于另一个IO () IO () }。 putStrLn "3"“等于”print 3吗?它们都具有相同的可观察效果,​​但运行时如何确定在一般情况下?并且你不能说“如果它们产生相同的值,它们就是等价的”,因为==的返回类型必须是IO Bool,而这不是{Eq的正确签名。 1}}。所以我们只是不给IO一个Eq实例,这没关系 - 我无法想出一个合理的例子来说明这样的实例何时有用。

另请注意,“IO”没有Monoid个实例(无论如何都是错误的类型)。您正在使用的mappend来自Monoid a => Monoid (IO a)的实例 - 也就是说,IO配方可以生成本身为Monoid的类型。 IO的{​​{1}}个实例只是“捎带”在基础Monoid实例上。