Back when I first learned some Haskell, I found out about monads. After understanding “enough to be dangerous”, I figured I could port the totally cool Quantum::Entanglement perl module to a Haskell monad. Unfortunately, such a task was not possible. I ran into trouble when the monadic bind needed to use an Eq instance, which of course it cannot because monadic bind has to work for all types.
But there is a deeper reason that I couldn’t do it. It’s because I needed to do something special with the input to quantum combinators, thus the control structure was in fact an arrow and not a monad. Well, probably an arrow. I just learned how to use them today. Anyway, the results are pretty promising. Check it out, there’s proper entanglement:
proc () -> do -- this binds (x,y) to either the tuple ("hello","world") with probability -- amplitude 1, or ("foo", "bar") with probability amplitude 1. (x,y) <- entangle -< [(("hello", "world"), 1 :+ 0) ,(("foo", "bar"), 1 :+ 0) ] qPutStr -< x qPutStr -< y qPutStr -< show (x,y)
Will output helloworld(“hello”,”world”) half the time and foobar(“foo”,”bar”) half the time, but never any other combinations.
“Well,” you say, “entangle might just choose a random alternative right when you bind it, there’s nothing special about that!”. Well, wait until you see the interference features:
makeStates = proc () -> do -- return a variable in the superposition |4> - |-4> + i|3> entangle -< [( 4, 1 :+ 0) ,(-4, -1 :+ 0) ,( 3, 0 :+ 1) ] demo1 = proc () -> do x <- makeStates -< () qPutStr -< show x demo2 = proc () -> do x <- makeStates -< () qPutStr -< show (x^2)
demo1 prints out 4, -4, and 3 with equal probability, as expected. However, demo2 has some interesting behavior. Since 4 and -4 both have the same square, 16, and their probability amplitudes are 1 and -1, respectively, they cancel each other out. So demo2 will only ever print 9.
It keeps all states around until you do some I/O, currently only supported is qPutStr. It then collapses the system to one of the eigenstates specified by qPutStr’s argument’s Eq implementation, choosing randomly according to the given probability amplitudes. I do wonder if I can lift the IO monad into this arrow without compromising its safety (i.e. can you observe states without collapsing them?). I’ll have to learn more about arrows first, but my first tests indicate that it is in fact safe to do that.
Writing this module was a very strange experience. I’m not really sure how it works. I sorta followed how the list monad works, since it does something similar, adding features here and there, and writing functions based on what I thought their types should be. It only typechecked twice, the first time there was a bug. I decided that it must be the only part of the implementation that made me uneasy: the fact that it sometimes discarded its universally quantified dummy argument in the collapse method. I fixed more type errors, and the second time it worked… perfectly. And if someone asked me to explain how, I really couldn’t tell them.
This all of course gives me a very high opinion of Haskell. This is a module which does something which is not a “normal” thing to do, has some complex logic with quantum interference and entanglement, and I can write it correctly without understanding it.