{-|
Module      : FunQ
Description : Main library
Stability   : experimental

Exports the language and simulator
-}
module FunQ 
    ( -- * Core operations
      new
    , measure
    , ndist
    , dist
    , controlbit

    -- * Core types
    , QBit
    , Bit
    , QM
    
    -- * Gates
    , pauliX
    , pauliY
    , pauliZ
    , hadamard
    , phase
    , phasePi8
    , cnot
    , identity
    , swap
    , tdagger
    , fredkin
    , toffoli
    , urot
    , crot
    , qft

    -- * Simulators
    , run
    , runDebug

    -- * Utils
    , bell
    , bellMeasure

    ) where

import Control.Monad ( replicateM, mapM )
import Lib.QM ( QM, QBit, run, runDebug )
import Lib.Core
    ( Bit,
      new,
      measure,
      controlbit,
      ndist,
      dist )
import Lib.Gates
    ( cnot,
      hadamard,
      identity,
      pauliX,
      pauliY,
      pauliZ,
      phase,
      phasePi8,
      swap,
      tdagger,
      fredkin,
      toffoli,
      urot,
      crot,
      qft )

-- | Prepares bell state
bell :: (Bit, Bit) -> QM (QBit, QBit)
bell :: (Bit, Bit) -> QM (QBit, QBit)
bell (a :: Bit
a,b :: Bit
b) = do
    QBit
qa <- Bit -> QM QBit
new Bit
a
    QBit
qb <- Bit -> QM QBit
new Bit
b
    QBit -> QM QBit
hadamard QBit
qa
    (QBit, QBit) -> QM (QBit, QBit)
cnot (QBit
qa, QBit
qb)

-- | Performs bell measurement
bellMeasure :: (QBit, QBit) -> QM (Bit, Bit)
bellMeasure :: (QBit, QBit) -> QM (Bit, Bit)
bellMeasure (x :: QBit
x,y :: QBit
y) = do
    (QBit, QBit) -> QM (QBit, QBit)
cnot (QBit
x,QBit
y)
    QBit -> QM QBit
hadamard QBit
x
    Bit
m_x <- QBit -> QM Bit
measure QBit
x
    Bit
m_y <- QBit -> QM Bit
measure QBit
y
    (Bit, Bit) -> QM (Bit, Bit)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bit
m_x,Bit
m_y)