Is it possible to create a Monad that count the number of instructions?

妖精的绣舞 提交于 2020-12-26 05:55:47

问题


Thinking about monad, it came to me the idea of a monad as the way to break with the Von Neumann architecture. The Von Neumann architecture uses a set of instructions (called program) to change the data in memory and the execution of each instruction of the program updates a program counter to know whom instruction is the next to execute.

If we think about the Von Neumann architecture as a monad, the bind operator (>>=) update the program counter. We can make a Monad that break Von Neumann architecture to do more in the bind. As an example, we can have a Monad that count the number of instructions executed in our programs.

But, when I tried to implement that Monad in haskell as:

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

I notice it'll break de Monads laws, e.g:

return x >>= f            /=   f x

do
   a <- return 3
   return a

do 
   return 3

The two blocks are the same because the monad laws, but they'll return something different because they have different number of instructions (sentences)

Do I made something wrong? or Is it not possible to have such Monad?


回答1:


Strictly speaking, any such "monad" breaks the monad laws and is thus... not a monad. See this previous question for details. In other words - your guess is correct, it is not possible to have such a monad.




回答2:


As another answer already mentioned, no lawful monad can count just the number of binds. But there is a way to count a related quantity: the number of binds minus the number of returns. This is still useful since it lets you count the number of nontrivial monadic operations.

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)

Here's some quick justifications for why this is lawful:

-- 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:


Your implementation throws away the number of steps in f. Shouldn't you add them?

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


来源:https://stackoverflow.com/questions/7956668/is-it-possible-to-create-a-monad-that-count-the-number-of-instructions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!