答案...</h2>
在这种方法中,我收到错误“异常:未定义:信号上的 Eq”
那是因为Eq
for 的实例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
from 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) = ...
现在我们可以做什么d
?d
在我们的例子中有类型D Bool
。让我们看一下 , 的定义low
,high
以及 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 E
,Lit
是后者的构造函数之一。所以我们实际上可以对toRep
目前和目前为止的事情进行模式匹配:
bitToBool (Signal _ d) = case unD d of
Lit r -> ...
_ -> False
toRep
有双fromRep
。并且pureX
具有某种双重性unX
,在这种情况下导致Just Bool
or Nothing
。我们可以使用fromMaybe
fromData.Maybe
来完成我们通过堪萨斯熔岩代码的小旅程:
bitToBool (Signal _ d) =
case unD d of
Lit r -> fromMaybe False . unX . fromRep $ r
_ -> False
不幸的是,我无法在我的系统上安装 kansas-lava,因此无法测试这个解决方案,但除非我错过了一些东西,否则至少应该进行类型检查。
......和悲伤的现实
现在我们已经看到将 a 转换回 a是可能的,但这并不明智。它可能会键入 check,但.Signal i Bool
Bool
unsafePerformIO
最后,您要从其Signal
上下文中删除一个布尔值。但是,由于这最后是硬件/VHDL,所以这并不明智:
您不能以任何明智的方式将 Signal 转换为 Bool。信号随“时间”而变化,因此将其与静态布尔值进行比较没有什么意义。这就是为什么没有位比较功能的原因。所以,你在这里走错了路。–<a href="https://stackoverflow.com/questions/23467604/haskell-bit-to-bool-error/23468568?noredirect=1#comment35995071_23467604">augustss
事实上,从我的角度来看, forEq
和Ord
实例不应该存在。Signal
此外,一些构造函数根本不应该被导出,作为重复提示:
augustuss 在问题评论中提出了一个重要问题:即使构造函数被导出,您是否应该访问信号的表示?–双倍体
但是,这最终取决于您的动机,因为两个原始问题都已得到解答。不幸的是,我无法回答新提出的问题“这有意义吗”,这取决于在该领域拥有更多专业知识的其他人。