2

我正在编写一个函数,将位转换为堪萨斯熔岩中的布尔值。我可以通过两种方式做到这一点,但它们都不起作用。

该函数必须执行以下操作:

  • 接收一点(低或高)
  • 将其转换为相应的布尔值 => False 如果它是低的并且它是高的

第一种方法:

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

在这种方法中,我收到错误“异常:未定义:信号上的 Eq”

第二种方法:

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

即使输入很高,此方法也始终返回 False。这应该有效,因为在另一段代码中我做了相反的操作,这有效。

我在这里做错了什么?

谢谢您的帮助

大安

4

1 回答 1

4

答案...</h2>

在这种方法中,我收到错误“异常:未定义:信号上的 Eq”

那是因为Eqfor 的实例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"

您无法比较任何两个信号。

我在这里做错了什么?

那不是lowhighfrom Utils,而是模式匹配。而且由于第一个模式总是匹配的,所以你总是 return False

…面包屑…</h2>

免责声明:我从未使用过 Kansas-Lava,我对硬件编程一无所知,而且我几乎是 Haskell 初学者。现在我已经失去了所有的信誉,让我们开始一段旅程Bool吧!

为了从 a 中得到一些东西Signal,我们需要知道aSignal什么:

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

太好了,我们实际上可以在以下位置进行模式匹配Signal

bitToBool (Signal _ d) = ...

现在我们可以做什么dd在我们的例子中有类型D Bool。让我们看一下 , 的定义lowhigh以及 helperpureS以获得一些灵感:

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 ELit是后者的构造函数之一。所以我们实际上可以对toRep目前和目前为止的事情进行模式匹配:

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

toRep有双fromRep。并且pureX具有某种双重性unX,在这种情况下导致Just Boolor Nothing。我们可以使用fromMaybefromData.Maybe来完成我们通过堪萨斯熔岩代码的小旅程:

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

不幸的是,我无法在我的系统上安装 kansas-lava,因此无法测试这个解决方案,但除非我错过了一些东西,否则至少应该进行类型检查。

......和悲伤的现实

现在我们已经看到将 a 转换回 a是可能的,但这并不明智。它可能会键入 check,但.Signal i BoolBoolunsafePerformIO

最后,您要从其Signal上下文中删除一个布尔值。但是,由于这最后是硬件/VHDL,所以这并不明智:

您不能以任何明智的方式将 Signal 转换为 Bool。信号随“时间”而变化,因此将其与静态布尔值进行比较没有什么意义。这就是为什么没有位比较功能的原因。所以,你在这里走错了路。–<a href="https://stackoverflow.com/questions/23467604/haskell-bit-to-bool-error/23468568?noredirect=1#comment35995071_23467604">augustss

事实上,从我的角度来看, forEqOrd实例不应该存在。Signal此外,一些构造函数根本不应该被导出,作为重复提示:

augustuss 在问题评论中提出了一个重要问题:即使构造函数被导出,您是否应该访问信号的表示?–双倍体

但是,这最终取决于您的动机,因为两个原始问题都已得到解答。不幸的是,我无法回答新提出的问题“这有意义吗”,这取决于在该领域拥有更多专业知识的其他人。

于 2014-05-05T08:56:51.737 回答