module ZkFold.Symbolic.Data.Eq.Structural where

import           Data.Function             (id)
import           Data.List                 (null, zipWith)

import           ZkFold.Symbolic.Compiler
import           ZkFold.Symbolic.Data.Bool
import           ZkFold.Symbolic.Data.Eq

newtype Structural a = Structural a
-- ^ A newtype wrapper for easy definition of Eq instances.

instance SymbolicData a x => Eq (Bool (ArithmeticCircuit a)) (Structural x) where
    Structural x
x == :: Structural x -> Structural x -> Bool (ArithmeticCircuit a)
== Structural x
y =
        let x' :: [ArithmeticCircuit a]
x' = forall a x. SymbolicData a x => x -> [ArithmeticCircuit a]
pieces @a x
x
            y' :: [ArithmeticCircuit a]
y' = x -> [ArithmeticCircuit a]
forall a x. SymbolicData a x => x -> [ArithmeticCircuit a]
pieces x
y
            zs :: [Bool (ArithmeticCircuit a)]
zs = (ArithmeticCircuit a
 -> ArithmeticCircuit a -> Bool (ArithmeticCircuit a))
-> [ArithmeticCircuit a]
-> [ArithmeticCircuit a]
-> [Bool (ArithmeticCircuit a)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith ArithmeticCircuit a
-> ArithmeticCircuit a -> Bool (ArithmeticCircuit a)
forall b a. Eq b a => a -> a -> b
(==) [ArithmeticCircuit a]
x' [ArithmeticCircuit a]
y'
         in if [Bool (ArithmeticCircuit a)] -> Bool
forall a. [a] -> Bool
forall (t :: Type -> Type) a. Foldable t => t a -> Bool
null [Bool (ArithmeticCircuit a)]
zs
              then Bool (ArithmeticCircuit a)
forall b. BoolType b => b
true
              else (Bool (ArithmeticCircuit a) -> Bool (ArithmeticCircuit a))
-> [Bool (ArithmeticCircuit a)] -> Bool (ArithmeticCircuit a)
forall b (t :: Type -> Type) x.
(BoolType b, Functor t, Foldable t) =>
(x -> b) -> t x -> b
all1 Bool (ArithmeticCircuit a) -> Bool (ArithmeticCircuit a)
forall a. a -> a
id [Bool (ArithmeticCircuit a)]
zs

    Structural x
x /= :: Structural x -> Structural x -> Bool (ArithmeticCircuit a)
/= Structural x
y =
        let x' :: [ArithmeticCircuit a]
x' = forall a x. SymbolicData a x => x -> [ArithmeticCircuit a]
pieces @a x
x
            y' :: [ArithmeticCircuit a]
y' = x -> [ArithmeticCircuit a]
forall a x. SymbolicData a x => x -> [ArithmeticCircuit a]
pieces x
y
            zs :: [Bool (ArithmeticCircuit a)]
zs = (ArithmeticCircuit a
 -> ArithmeticCircuit a -> Bool (ArithmeticCircuit a))
-> [ArithmeticCircuit a]
-> [ArithmeticCircuit a]
-> [Bool (ArithmeticCircuit a)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith ArithmeticCircuit a
-> ArithmeticCircuit a -> Bool (ArithmeticCircuit a)
forall b a. Eq b a => a -> a -> b
(==) [ArithmeticCircuit a]
x' [ArithmeticCircuit a]
y'
         in if [Bool (ArithmeticCircuit a)] -> Bool
forall a. [a] -> Bool
forall (t :: Type -> Type) a. Foldable t => t a -> Bool
null [Bool (ArithmeticCircuit a)]
zs
              then Bool (ArithmeticCircuit a)
forall b. BoolType b => b
false
              else Bool (ArithmeticCircuit a) -> Bool (ArithmeticCircuit a)
forall b. BoolType b => b -> b
not ((Bool (ArithmeticCircuit a) -> Bool (ArithmeticCircuit a))
-> [Bool (ArithmeticCircuit a)] -> Bool (ArithmeticCircuit a)
forall b (t :: Type -> Type) x.
(BoolType b, Functor t, Foldable t) =>
(x -> b) -> t x -> b
all1 Bool (ArithmeticCircuit a) -> Bool (ArithmeticCircuit a)
forall a. a -> a
id [Bool (ArithmeticCircuit a)]
zs)