是否可以创建一个计算指令数量的Monad?

时间:2011-10-31 16:35:37

标签: haskell monads

考虑到monad,我想到了monad作为打破Von Neumann架构的方法。冯·诺依曼架构使用一组指令(称为程序)来改变存储器中的数据,并且程序的每个指令的执行更新程序计数器以知道下一个执行的指令。

如果我们将Von Neumann架构视为monad,则绑定运算符(>> =)更新程序计数器。我们可以让Monad打破Von Neumann架构,在绑定中做更多事情。作为一个例子,我们可以有一个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定律,但是它们会返回不同的东西,因为它们有不同数量的指令(句子)

我做错了吗?或者不可能有这样的Monad?

3 个答案:

答案 0 :(得分:8)

严格地说,任何这样的“monad”都违反了monad法律,因此......不是monad。见previous question for details。换句话说 - 你的猜测是正确的,不可能有这样的monad。

答案 1 :(得分:3)

作为已经提到的另一个答案,没有合法的monad可以仅计算绑定数。但是有一种方法可以计算相关数量:绑定数量减去退货数量。这仍然很有用,因为它可以让您计算非平凡的单子运算的次数。

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

答案 2 :(得分:1)

您的实现会丢弃f中的步骤数。你不应该加他们吗?

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