看看这段IO代码:
Prelude> let e = return () :: IO ()
Prelude> e `mappend` e
Prelude> let y = e `mappend` e
Prelude> :t y
y :: IO ()
Run Code Online (Sandbox Code Playgroud)
编辑显然,据我所知,IO有一个Monoid实例.
但是,true为了服从Monoid第三定律,不应该进行以下评估吗?
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
Run Code Online (Sandbox Code Playgroud)
Ian*_*nry 11
第三独异的法律规定,e <> (e <> e) = (e <> e) <> e(以用于更易于型缀运算符mappend),不说e <> (e <> e) == (e <> e) <> e(注意=对比==).
它表达了一个等价 - 实际上,表达mappend应该是关联的 - 不要求所有的Monoids也必须是Eq类型类的实例,==来源于.
另一种说法是:它表达了关于mappend函数行为的高级概念,没有呈现有效的Haskell代码,应该对任何特定的东西进行评估.
Monoid例如[()],某些类型的s - 也碰巧有一个Eq实例.但有些人(IO ()比如这里的实例)没有,这没关系.
旁注:给出
IO一个Eq实例并没有多大意义,因为它几乎不可能确定某个实例IO ()是否等同于另一个实例IO ().是putStrLn "3""平等"print 3吗?它们都具有相同的可观察效果,但运行时如何确定在一般情况下?并且你不能说"如果它们产生相同的值,它们是等价的",因为那时返回类型==必须是aIO Bool,而这不是正确的签名Eq.所以我们只是不给出IO一个Eq实例,这没关系 - 我无法想出一个合理的例子,说明这样的实例何时有用.
另请注意," IO"没有Monoid实例(无论如何都是错误的类型).在mappend为您正在使用来自实例Monoid a => Monoid (IO a)就是IO配方生产,它们本身的类型- Monoid秒.IO的Monoid实例只是在背景实例上"背驮" Monoid.