Answers…
In this method I get the error "Exception: undefined: Eq over a signal"
That's because the Eq instance for Signal c a is as such:
instance (Rep a, Eq a) => Eq (Signal c a) where
-- Silly question; never True; can be False.
(Signal _ _) == (Signal _ _) = error "undefined: Eq over a Signal"
You can't compare any two signals.
What am I doing wrong here?
That's not low or high from Utils, but instead pattern matching. And since the first pattern always matches, you always return False.
…breadcrumbs…
Disclaimer: I've never used Kansas-Lava, I have no idea about hardware programming, and I'm pretty much a Haskell beginner. Now that I've lost all my credibility, lets start on a journey to get that Bool!
In order to get something out of a Signal, we need to know what a Signal is:
data Signal (c :: *) a = Signal (S.Stream (X a)) (D a)
Great, we can actually pattern match on Signal:
bitToBool (Signal _ d) = ...
Now what can we do with d? d has type D Bool in our case. Lets have a look at the definition of low, high, and also the helper pureS to get some inspiration:
pureS :: (Rep a) => a -> Signal i a
pureS a = Signal (pure (pureX a)) (D $ Lit $ toRep $ pureX a)
high :: (sig ~ Signal i) => sig Bool
high = pureS True
low :: (sig ~ Signal i) => sig Bool
low = pureS False
Note the Rep class, it gets important later. D is a newtype wrapper for Driver E, Lit is one of the constructors for the latter. So we can actually pattern match for the things up to toRep and are currently at this point:
bitToBool (Signal _ d) = case unD d of
Lit r -> ...
_ -> False
toRep has a dual fromRep. And pureX has a somewhat dual unX, which in this case leads to Just Bool or Nothing. We can use fromMaybe from Data.Maybe to finish our little journey through the Kansas Lava code:
bitToBool (Signal _ d) =
case unD d of
Lit r -> fromMaybe False . unX . fromRep $ r
_ -> False
Unfortunately, I couldn't install kansas-lava on my system and therefore couldn't test this solution, but unless I've missed something everything should at least type check.
…and sad reality
Now that we've seen that it might be possible to transform a Signal i Bool back to a Bool, it isn't wise. It might type check, but so does unsafePerformIO.
In the end, you're removing a boolean value from its Signal context. However, since this is hardware/VHDL at the end, that's not really sensible:
You can't turn a Signal into a Bool in any sensible way. Signals vary over "time", so comparing it with a static boolean makes little sense. That's why there's no comparison function for bits. So, you're on the wrong track here. –augustss
In fact, the Eq and Ord instances for Signal shouldn't exist from my point of view. Also, some of the constructors shouldn't be exported at all, as duplode hints:
augustuss raises an important issue in the question comments: even if the constructors are exported, are you supposed to access the representation of a signal? –duplode
However, it ultimately depends on your motives, as both original questions have been answered. Unfortunately, I cannot answer the new risen question "Does that make sense", that's up to someone else who has more expertise in this field.