-- | The Deustch Oracle algorithm
module Deutsch where

import FunQ

type Oracle = (QBit, QBit) -> QM (QBit, QBit)

-- | An oracle with a constant function
constant :: Oracle
constant :: Oracle
constant (x :: QBit
x,y :: QBit
y) = do
    QBit
z <- Bit -> QM QBit
new 0
    Oracle
swap (QBit
z, QBit
x)
    Oracle
cnot (QBit
x, QBit
y)
    Oracle
swap (QBit
z, QBit
x)
    Oracle
forall (m :: * -> *) a. Monad m => a -> m a
return (QBit
x, QBit
y) 

-- | An oracle with a balanced function
balanced :: Oracle
balanced :: Oracle
balanced (x :: QBit
x,y :: QBit
y) = do
    QBit -> QM QBit
pauliX QBit
x
    Oracle
cnot (QBit
x,QBit
y)
    QBit -> QM QBit
pauliX QBit
x
    Oracle
forall (m :: * -> *) a. Monad m => a -> m a
return (QBit
x, QBit
y)

-- | Will return a 1 if balanced and 0 if constant.
deutsch :: Oracle -> QM Bit
deutsch :: Oracle -> QM Bit
deutsch oracle :: Oracle
oracle = do
    QBit
x <- Bit -> QM QBit
new 0
    QBit
y <- Bit -> QM QBit
new 1
    QBit -> QM QBit
hadamard QBit
x
    QBit -> QM QBit
hadamard QBit
y
    Oracle
oracle (QBit
x, QBit
y)
    QBit -> QM QBit
hadamard QBit
x
    QBit -> QM Bit
measure QBit
x