查看此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
的类型。 IO
的Monoid
实例只是在基础Monoid
实例上“背负”。
关于haskell - 第三类半定律和IO?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38493804/