问题
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