Ошибка битов Haskell в bool

Я пишу функцию, которая немного преобразует в bool в Kansas Lava. Я могу сделать это двумя способами, но ни один из них не работает.

Функция должна делать следующее:

  • Получите немного (низкий или высокий)
  • Преобразуйте его в соответствующее логическое значение => False, если оно низкое, и True, если оно высокое.

Первый способ:

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

В этом методе я получаю ошибку «Exception: undefined: Eq over a signal».

Второй способ:

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

Этот метод всегда возвращает False, даже если входной сигнал высокий. Это должно сработать, потому что в другом фрагменте кода я делаю обратное, что работает.

Что я здесь делаю не так?

Спасибо за помощь

Даан


person Daan Mouha    schedule 05.05.2014    source источник
comment
Какое определение для Signal?   -  person Lee Duhem    schedule 05.05.2014
comment
Не знаю Lava, но я предполагаю, что у вас проблема с прописными / строчными буквами. low - это просто переменная в Haskell - она ​​такая же, как если бы вы использовали x или _. Может, вы имели в виду Low и High?   -  person Chris    schedule 05.05.2014
comment
Функция, в которой он отлично работает: boolToBit :: Bool - ›Signal i Bool boolToBit False = low boolToBit True = high Так что я не думаю, что это Low и High. В Канзасе Lava Signal примерно такой же, как Bit в York Lava, но с другими функциями.   -  person Daan Mouha    schedule 05.05.2014
comment
@Daan Mouha Если это обычный Haskell, ваша функция bitToBool точно такая же, как bitToBool _ = False (или bitToBool = const False, если хотите). Если вы можете включить предупреждения компилятора ghc в Lava, он будет выдавать предупреждения о совпадении совпадений с шаблоном (поскольку вторая строка недоступна) и неиспользуемых определениях.   -  person Chris    schedule 05.05.2014
comment
Вы не можете каким-либо разумным способом превратить Сигнал в Bool. Сигналы меняются со временем, поэтому сравнение его со статическим логическим значением не имеет смысла. Вот почему нет функции сравнения битов. Итак, вы здесь ошиблись.   -  person augustss    schedule 05.05.2014


Ответы (1)


Ответы…

В этом методе я получаю ошибку «Exception: undefined: Eq over a signal».

Это потому, что экземпляр Eq для Signal c a таков:

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"

Вы не можете сравнивать любые два сигнала.

Что я здесь делаю не так?

Это не low или high из _6 _, но вместо этого сопоставление с образцом. И поскольку первый шаблон всегда совпадает, вы всегда возвращаете False.

…панировочные сухари…

Отказ от ответственности: я никогда не использовал Kansas-Lava, я понятия не имею об аппаратном программировании, и я в значительной степени новичок в Haskell. Теперь, когда я потерял всякое доверие, давайте начнем путешествие, чтобы получить это Bool!

Чтобы получить что-то от Signal, нам нужно знать что такое Signal:

data Signal (c :: *) a = Signal (S.Stream (X a)) (D a)

Отлично, мы действительно можем сопоставить с образцом Signal:

bitToBool (Signal _ d) = ...

Что мы можем сделать с d? d в нашем случае имеет тип D Bool. Давайте посмотрим на определение low, high, а также помощник _ 19_, чтобы вдохновиться:

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

Обратите внимание на Rep class , это станет важным позже. D - это newtype оболочка для Driver E, _25 _ является одним из конструкторов последнего. Таким образом, мы можем фактически сопоставить с образцом вещи вплоть до toRep и в настоящее время находимся в этой точке:

bitToBool (Signal _ d) = case unD d of
                             Lit r -> ...
                             _     -> False

toRep имеет двойной fromRep. И pureX имеет несколько двойственный unX < / a>, что в данном случае приводит к Just Bool или Nothing. Мы можем использовать fromMaybe из Data.Maybe, чтобы завершить наше небольшое путешествие по коду Канзасской лавы:

bitToBool (Signal _ d) = 
    case unD d of
        Lit r -> fromMaybe False . unX . fromRep $ r
        _     -> False

К сожалению, я не смог установить kansas-lava в своей системе и, следовательно, не смог протестировать это решение, но, если я что-то не пропустил, все должно, по крайней мере, проверить тип.

… И печальная реальность

Теперь, когда мы увидели, что может быть возможным преобразовать Signal i Bool обратно в Bool, это неразумно. Это может быть проверка типа, но unsafePerformIO тоже.

В конце концов, вы удаляете логическое значение из Signal контекста. Однако, поскольку в конечном итоге это аппаратное обеспечение / VHDL, это не совсем разумно:

Вы не можете каким-либо разумным способом превратить Сигнал в Bool. Сигналы меняются с течением времени, поэтому сравнение их со статическим логическим значением не имеет особого смысла. Вот почему нет функции сравнения битов. Итак, вы здесь ошиблись. - августа

Фактически, экземпляры Eq и Ord для Signal не должны существовать с моей точки зрения. Кроме того, некоторые конструкторы вообще не следует экспортировать, как подсказывает duplode:

В комментариях к вопросу augustuss поднимает важный вопрос: даже если конструкторы экспортируются, предполагается ли, что вы получите доступ к представлению сигнала? –duplode

Однако в конечном итоге это зависит от ваших мотивов, поскольку на оба первоначальных вопроса были даны ответы. К сожалению, я не могу ответить на вновь возникший вопрос «Имеет ли это смысл?», Это зависит от кого-то другого, у кого больше опыта в этой области.

person Zeta    schedule 05.05.2014
comment
Есть ли причина использовать high :: (sig ~ Signal i) => sig Bool вместо high :: Signal i Bool? Они выглядят одинаково для меня. - person chi; 05.05.2014
comment
@chi: Они должны быть эквивалентными, но опять же, Я в значительной степени новичок в Haskell ^^. Может, авторы сочли, что это представление красивее. С другой стороны, они создали экземпляры Eq и Ord для Signal, которые терпят неудачу ни на чем, кроме max и min - просто ради max и min, что ужасно imho. - person Zeta; 05.05.2014
comment
В комментариях к вопросу augustuss поднимает важный вопрос: даже если конструкторы экспортируются, предполагается ли, что вы получите доступ к представлению сигнала? - person duplode; 05.05.2014
comment
@duplode: Наверное, нет. Я разговаривал с кем-то, кто немного разбирается в VHDL и аппаратном программировании, и он был на одном уровне с августом. - person Zeta; 06.05.2014
comment
Ждать. Почему Signal должен начинаться с Eq экземпляра? - person ; 06.05.2014
comment
@Rhymoid: Честно говоря, я понятия не имею и считаю, что это неправильно. Я догадывался, что авторы хотят использовать max и min из Ord, которому также нужен экземпляр Eq, но быстрый поиск в репозитории показал, что даже экземпляр Ord вообще не используется. Кажется, что он там и может вызвать ошибку времени выполнения. Ура. - person Zeta; 06.05.2014
comment
@Zeta: возможно, он нужен для поддержки экземпляра Num для старых GHC. - person ; 06.05.2014
comment
Этот код работает. Не импортируйте только Language.KansasLava, но также импортируйте Language.KansasLava.Signal в. Еще есть ошибка, что он не знает, что такое Signal. - person Daan Mouha; 07.05.2014