【问题标题】:Is it possible to create a Monad that count the number of instructions?是否可以创建一个计算指令数量的 Monad?
【发布时间】: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 和&gt;&gt;=s 更改计数器。 (所以return 返回0f &gt;&gt;= g 返回counter f + gounter g)。然后,所有的单子定律都被遵守了。如果您想将某些操作计为操作,则可以改为使用类似于return 的操作,称为op,它计为1。由于 monad 法则没有特别对待op,它们不会干扰op。此外,通过这种方式,您可以清楚地区分“计数”的事物和不“计数”的事物。
  • 我认为上面@fuz 建议的公式相当于Writer (Sum Int)。每个值都有一个附加的计数器,组合操作将它们的计数器相加。

标签: haskell monads


【解决方案1】:

严格来说,任何这样的“monad”都违反了 monad 法则,因此......不是 monad。请参阅此previous question for details。换句话说——你的猜测是正确的,不可能有这样的单子。

【讨论】:

    【解决方案2】:

    正如已经提到的另一个答案,任何合法的单子都不能只计算绑定的数量。但是有一种方法可以计算相关数量:绑定数量减去退货数量。这仍然很有用,因为它可以让您计算非平凡一元操作的数量。

    instance Functor Counter where
        fmap f (Counter n x) = Counter n (f x)
    
    instance Applicative Counter where
        pure = Counter (-1)
        Counter n1 f <*> Counter n2 x = Counter (n1 + n2 + 1) (f x)
    
    instance Monad Counter where
        Counter n1 a >>= f = let Counter n2 b = f a in Counter (n1 + n2 + 1) b
        return = Counter (-1)
    

    以下是为什么这是合法的一些快速理由:

    -- left identity
    return x >>= f = f x
    Counter (-1) x >>= f = f x
    let Counter n2 b = f x in Counter ((-1) + n2 + 1) b = f x
    let Counter n2 b = f x in Counter n2 b = f x
    f x = f x
    
    -- right identity
    m >>= return = m
    Counter n1 a >>= return = Counter n1 a
    let Counter n2 b = return a in Counter (n1 + n2 + 1) b = Counter n1 a
    let Counter n2 b = Counter (-1) a in Counter (n1 + n2 + 1) b = Counter n1 a
    Counter (n1 + (-1) + 1) a = Counter n1 a
    Counter n1 a = Counter n1 a
    
    -- associativity
    m >>= f >>= g = m >>= \x -> f x >>= g
    Counter n1 a >>= f >>= g = Counter n1 a >>= \x -> f x >>= g
    (let Counter n2 b = f a in Counter (n1 + n2 + 1) b) >>= g = Counter n1 a >>= \x -> f x >>= g
    (let Counter n2 b = f a in Counter (n1 + n2 + 1) b) >>= g = let Counter n2 b = (\x -> f x >>= g) a in Counter (n1 + n2 + 1) b
    (let Counter n2 b = f a in Counter (n1 + n2 + 1) b) >>= g = let Counter n2 b = f a >>= g in Counter (n1 + n2 + 1) b
    let Counter n2 b = f a in (Counter (n1 + n2 + 1) b >>= g) = let Counter n2 b = f a >>= g in Counter (n1 + n2 + 1) b
    let Counter n2 b = f a in (let Counter n3 c = g b in Counter ((n1 + n2 + 1) + n3 + 1) c) = let Counter n2 b = f a >>= g in Counter (n1 + n2 + 1) b
    let Counter n2 b = f a in (let Counter n3 c = g b in Counter (n1 + n2 + n3 + 2) c) = let Counter n2 b = f a >>= g in Counter (n1 + n2 + 1) b
    let Counter n2 b = f a; Counter n3 c = g b in Counter (n1 + n2 + n3 + 2) c = let Counter n2 b = f a >>= g in Counter (n1 + n2 + 1) b
    let Counter n2 b = f a; Counter n3 c = g b in Counter (n1 + n2 + n3 + 2) c = let Counter n2 b = (let Counter n3 c = f a in Counter n3 c) >>= g in Counter (n1 + n2 + 1) b
    let Counter n2 b = f a; Counter n3 c = g b in Counter (n1 + n2 + n3 + 2) c = let Counter n2 b = (let Counter n3 c = f a in Counter n3 c >>= g) in Counter (n1 + n2 + 1) b
    let Counter n2 b = f a; Counter n3 c = g b in Counter (n1 + n2 + n3 + 2) c = let Counter n2 b = (let Counter n3 c = f a in (let Counter n4 d = g c in Counter (n3 + n4 + 1) d)) in Counter (n1 + n2 + 1) b
    let Counter n2 b = f a; Counter n3 c = g b in Counter (n1 + n2 + n3 + 2) c = let Counter n2 b = (let Counter n3 c = f a; Counter n4 d = g c in Counter (n3 + n4 + 1) d) in Counter (n1 + n2 + 1) b
    let Counter n2 b = f a; Counter n3 c = g b in Counter (n1 + n2 + n3 + 2) c = let Counter n3 c = f a; Counter n4 d = g c in Counter (n1 + (n3 + n4 + 1) + 1) d
    let Counter n2 b = f a; Counter n3 c = g b in Counter (n1 + n2 + n3 + 2) c = let Counter n3 c = f a; Counter n4 d = g c in Counter (n1 + n3 + n4 + 2) d
    

    【讨论】:

      【解决方案3】:

      您的实现丢弃了 f 中的步数。你不应该添加它们吗?

        (Counter n1 a) >>= f = let Counter n2 b = f a
                           in (Counter (n1+n2) b)
      

      【讨论】:

      • 你是对的,但它不能解决单子定律。应该是 (n1+n2+1)。
      猜你喜欢
      • 2015-07-21
      • 2013-09-26
      • 2010-10-23
      • 1970-01-01
      • 2012-05-13
      • 1970-01-01
      • 1970-01-01
      • 2023-01-08
      • 2022-06-13
      相关资源
      最近更新 更多