为了便于阅读,我想使用时钟频率值作为类型索引。但是,我需要检查它们与时钟域的兼容性,时钟域将它们的速度表示为周期长度。
为了更具体一点,假设我具有以下数据类型,出于可读性考虑,使用其类型的时钟速率(以Hz为单位);在实际程序中,这可能是VGA计时:
data Rate (rate :: Nat) = MkRate
rate :: Rate 25175000
rate = MkRate
但是,我需要将其与代表时钟周期(以皮秒为单位)的类型一起使用;在真正的CLaSH程序中,那将是时钟域本身。
data Period (ps :: Nat) = MkPeriod
period :: Period 39721
period = MkPeriod
现在问题开始了,因为25.175 MHz的一个周期不是整数皮秒。首先,让我们尝试使用乘法:
connect1 :: ((rate * ps) ~ 1000000000000) => Rate rate -> Period ps -> ()
connect1 _ _ = ()
test1 :: ()
test1 = connect1 rate period
这以预期的方式失败:
../clash-sandbox/lib/src-clash/Cactus/Clash/VGA.hs:79:9: error:
• Couldn't match type ‘999976175000’ with ‘1000000000000’
arising from a use of ‘connect1’
• In the expression: connect1 rate period
In an equation for ‘test1’: test1 = connect1 rate period
|
79 | test1 = connect1 rate period
| ^^^^^^^^^^^^^^^^^^^^
我们可以尝试的另一种方法是类型级划分:
connect2 :: (ps ~ (1000000000000 `div` rate)) => Rate rate -> Period ps -> ()
connect2 _ _ = ()
test2 :: ()
test2 = connect2 rate period
但这似乎并没有减少:
../clash-sandbox/lib/src-clash/Cactus/Clash/VGA.hs:85:9: error:
• Couldn't match type ‘39721’ with ‘div0 1000000000000 25175000’
arising from a use of ‘connect2’
• In the expression: connect2 rate period
In an equation for ‘test2’: test2 = connect2 rate period
答案 0 :(得分:5)
结果是the ghc-typelits-extra
package的划分减少了;这让我写
connect :: (ps ~ (1000000000000 `Div` rate)) => Rate rate -> Period ps -> ()
test = connect rate period
,然后进行类型检查。