You probably want to find out if the two functions that the MakeGate
data constructors wrap always produce the same result of the same input.
We can only find this out by performing an exhaustive search: for both functions calculate the result for all possible inputs, and each time comparing the output. We thus could write it like:
type GateFunc = Bool -> Bool -> Bool
eqGate :: GateFunc -> GateFunc -> Bool
eqGate f g = f False False == g False False
&& f False True == g False True
&& f True False == g True False
&& f True True == g True True
and then write it as:
instance Eq Gate where
MakeGate f == MakeGate g = eqGate f g
The above is however not very elegant: we can do better by generating lists:
eqGate :: GateFunc -> GateFunc -> Bool
eqGate f g = (f <$> ft <*> ft) == (g <$> ft <*> ft)
where ft = [False, True]
Or even less code:
import Data.Function(on)
eqGate = on (==) ((<*> ft) . (<$> ft))
where ft = [False, True]
Note that for functions with a small (at least finite!) input space, and an output type that is an instance of Eq
, this can be done, but in general one can not compare two functions. Furthermore even if the two functions have a finite input space, it can go wrong (since the functions could get stuck into an infinite loop). Determining whether two functions are equal is an undecidable problem.