Haskell немного, чтобы bool ошибка

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

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

  • Получите немного (низкий или высокий)
  • Преобразуйте его в соответствующий логический => 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, даже если ввод высокий. Это должно работать, потому что в другом фрагменте кода я делаю обратное, что работает.

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

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

Даан

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 от Utils, но вместо сопоставления с образцом. И поскольку первый шаблон всегда совпадает, вы всегда возвращаете 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 а также помощник pureS чтобы получить вдохновение:

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 класс, это становится важным позже. D это newtype обертка для Driver E, Lit является одним из конструкторов для последнего. Таким образом, мы можем на самом деле сопоставить образец для вещей до toRep и в данный момент на этом этапе:

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

toRep имеет двойной fromRep, А также pureX имеет несколько двойной unX что в этом случае приводит к 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 каким-либо разумным способом. С течением времени сигналы меняются, поэтому сравнивать их со статическим логическим значением бессмысленно. Вот почему нет функции сравнения для битов. Итак, вы здесь не на том пути. - augustss

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

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

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

Другие вопросы по тегам