2

I'm writing a function which converts a bit to a bool in Kansas Lava. I can do this in two ways but neither of them works.

The function must do the following:

  • Receive a bit (low or high)
  • Convert it to its corresponding boolean => False if it's low and True of it's high

First method:

bitToBool :: Signal i Bool -> Bool
bitToBool x
  | x==low = False
  | otherwise = True

In this method I get the error "Exception: undefined: Eq over a signal"

Second method:

bitToBool :: Signal i Bool -> Bool
bitToBool low = False
bitToBool high = True

This method always returns False even if the input is high. This should work because in an another piece of code I do the reverse of this, which works.

What am I doing wrong here?

Thanks for the help

Daan

Sibi
  • 47,472
  • 16
  • 95
  • 163
Daan Mouha
  • 580
  • 1
  • 6
  • 20
  • What is the definition of `Signal`? – Lee Duhem May 05 '14 at 08:08
  • 2
    Don't know Lava, but I assume that you have a problem with uppercase/lowercase. `low` is just a variable in Haskell - it's the same as if you would have used `x` or `_`. Perhaps you meant `Low` and `High`? – Chris May 05 '14 at 08:11
  • The function in which it works fine: boolToBit :: Bool -> Signal i Bool boolToBit False = low boolToBit True = high So I don't think its Low and High. In Kansas Lava Signal is roughly the same as Bit in York Lava but with other features. – Daan Mouha May 05 '14 at 08:15
  • 2
    @Daan Mouha If this is regular Haskell, your function `bitToBool` is exactly the same as `bitToBool _ = False` (or `bitToBool = const False`, if you prefer). If you can enable ghc compiler warnings in Lava, it will give you warnings about overlapping pattern matches (because the 2nd line is unreachable) and unused definitions. – Chris May 05 '14 at 08:24
  • 3
    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 May 05 '14 at 15:53

1 Answers1

4

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.

Community
  • 1
  • 1
Zeta
  • 103,620
  • 13
  • 194
  • 236
  • Is there any reason behind using `high :: (sig ~ Signal i) => sig Bool` instead of `high :: Signal i Bool`? They look equivalent to me. – chi May 05 '14 at 10:57
  • @chi: They should be equivalent, but then again, *"I'm pretty much a Haskell beginner"* ^^". Maybe the authors thought that this representation is prettier. On the other hand, they created a `Eq` and `Ord` instances for `Signal` which fail on anything but `max` and `min` - just for the sake of `max` and `min`, which is awful imho. – Zeta May 05 '14 at 11:55
  • 1
    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 May 05 '14 at 16:51
  • @duplode: Probably not. I've talked to someone who knows a little bit about VHDL and hardware programming, and he was on par with augustuss. – Zeta May 05 '14 at 20:24
  • Wait. Why does `Signal` have an `Eq` instance to begin with? –  May 05 '14 at 22:11
  • @Rhymoid: Frankly, I have no idea and believe it's wrong. I guessed that the authors want to use `max` and `min` from `Ord`, which also needs an `Eq` instance, but a quick search in the repository revealed that even the `Ord` instance isn't used at all. It almost seems like it's there so that it can produce a runtime error. Yay. – Zeta May 06 '14 at 04:44
  • @Zeta: maybe it's there to support the `Num` instance, for older GHCs. –  May 06 '14 at 06:10
  • This code works. Don't import Language.KansasLava only, but also import Language.KansasLava.Signal to. Else there's an error that it doesn't know what Signal is. – Daan Mouha May 07 '14 at 09:00