1
votes

I created a new type with some functions

data Gate = MakeGate (Bool -> Bool -> Bool)
andGate = MakeGate (&&)
orGate = MakeGate (||)

Now I want to add this type to a new instance of Eq with pattern matching, but I actually get alot of error messages. What I tried so far is

instace Eq Gate where
    MakeGate True == MakeGate True = True

The Error Message is: "Couldn't match expected type 'Bool -> Bool -> Bool' with actual type 'Bool'" I was thinking that Bool -> Bool -> Bool means something similar to the (&&) or (||) functions. But it doesn't work that way.

What am I missing?

4

4 Answers

4
votes

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.

3
votes

You can't really pattern match functions in Haskell.

MakeGate is a constructor that has the type: (Bool -> Bool -> Bool) -> Gate But you're giving it a Bool (True). MakeGate True doesn't typecheck.

Maybe you meant MakeGate f == MakeGate g = f == g or something like that?

I'm not sure what you're trying to do, but function equivalence isn't trivial and pattern matching is for constructors, not functions.

I think what you really want is data Gate = AndGate | OrGate | ...

1
votes

MakeGate does not wrap a Boolean value; it wraps a function. I'm not sure how you would define an Eq instance for Gate, because you can't compare functions for equality. The syntax, though, would be

instance Eq Gate where
    (MakeGate f) == (MakeGate g) = ???

The ??? would be the actual equality test, but like I said, it's not clear what you would put here, because you can't use, for instance, f == g.

1
votes

You cannot define a meaningful Eq instance on your Gate type, since it contains a function, and functions cannot be compared for equality.

More to the point, though, your question seems confused about a variety of different things about Haskell specifically and higher-order functional programming in general. Consider finding a course, book, or other resource to help you learn in a structured, principled way. (Asking for such resources is off-topic on Stack Overflow, so I will refrain from making specific suggestions here.)