【发布时间】:2011-12-18 21:23:35
【问题描述】:
想到 monad,我想到了将 monad 作为打破冯诺依曼架构的方式的想法。冯诺依曼架构使用一组指令(称为程序)来更改内存中的数据,并且程序的每条指令的执行都会更新程序计数器以了解下一条要执行的指令。
如果我们将冯诺依曼架构视为一个单子,绑定运算符 (>>=) 会更新程序计数器。我们可以制作一个打破冯诺依曼架构的 Monad,以便在绑定中做更多事情。例如,我们可以有一个 Monad 来计算程序中执行的指令数。
但是,当我尝试在 haskell 中实现 Monad 时:
data Counter a = Counter Integer a
deriving( Show )
instance Monad Counter where
(Counter n1 a) >>= f = let Counter _ b = f a
in (Counter (n1+1) b)
return a = Counter 1 a
我注意到它会违反 de Monads 定律,例如:
return x >>= f /= f x
do
a <- return 3
return a
do
return 3
这两个块是相同的,因为单子定律,但它们会返回不同的东西,因为它们有不同数量的指令(句子)
我做错了什么吗?还是不可能有这样的Monad?
【问题讨论】:
-
这是一个很好的问题,你能重写一下让它更清楚吗?由于错误,阅读起来有点困难。
-
好吧,如果
returns 不算数,它似乎不会违反法律。 -
@Matt Fenwick,我重写了问题以修正语法。
-
@Zhen 好吧,我唯一的建议是停止
returns 和>>=s 更改计数器。 (所以return返回0和f >>= g返回counter f + gounter g)。然后,所有的单子定律都被遵守了。如果您想将某些操作计为操作,则可以改为使用类似于return的操作,称为op,它计为1。由于 monad 法则没有特别对待op,它们不会干扰op。此外,通过这种方式,您可以清楚地区分“计数”的事物和不“计数”的事物。 -
我认为上面@fuz 建议的公式相当于
Writer (Sum Int)。每个值都有一个附加的计数器,组合操作将它们的计数器相加。