With the following "toy model" of Clash:
{-# LANGUAGE RankNTypes, KindSignatures, DataKinds, FlexibleContexts #-}
-- Simplified model of platform definitions
data Domain = DomSys | Dom25
data Signal (dom :: Domain)
data Clock (dom :: Domain)
class HiddenClock (dom :: Domain)
withClock :: Clock dom -> (HiddenClock dom => r) -> r
withClock _ _ = undefined
I would like to use withClock
to close over the HiddenClock
constraint inside a local where
block. Suppose I have the following two toplevel definitions:
-- Simplified model of external standalone definitions
mainBoard :: (HiddenClock dom) => Signal dom -> Signal dom -> Signal dom -> (Signal dom, Signal dom)
mainBoard = undefined
peripherals :: (HiddenClock dom) => Signal dom -> Signal dom
peripherals = undefined
video
:: Clock domVid
-> Clock domSys
-> Signal domSys
-> Signal domSys
-> (Signal domVid, Signal domSys, Signal domSys)
video = undefined
then, I would like to write something like the following:
topEntity :: Clock Dom25 -> Clock DomSys -> Signal DomSys -> Signal Dom25
topEntity clkVid clkSys input = vga
where
(vga, vidRead, line) = video clkVid clkSys vidAddr vidWrite
(vidAddr, vidWrite) = withClock clkSys board
board = mainBoard vidRead line p
where
p = peripherals input
Unfortunately, GHC (at least as of 8.10.7) is unable to infer the correct type for board
, which causes withClock clkSys board
to not really close over the HiddenClock DomSys
constriant:
• No instance for (HiddenClock 'DomSys)
arising from a use of ‘mainBoard’
• In the expression: mainBoard vidRead line p
In an equation for ‘board’:
board
= mainBoard vidRead line p
where
p = peripherals input
In an equation for ‘topEntity’:
topEntity clkVid clkSys input
= vga
where
(vga, vidRead, line) = video clkVid clkSys vidAddr vidWrite
(vidAddr, vidWrite) = withClock clkSys board
board
= mainBoard vidRead line p
where
p = peripherals input
|
38 | board = mainBoard vidRead line p
| ^^^^^^^^^^^^^^^^^^^^^^^^
• No instance for (HiddenClock 'DomSys)
arising from a use of ‘peripherals’
• In the expression: peripherals input
In an equation for ‘p’: p = peripherals input
In an equation for ‘board’:
board
= mainBoard vidRead line p
where
p = peripherals input
|
40 | p = peripherals input
| ^^^^^^^^^^^^^^^^^
This can be worked around by adding a type signature to board
:
board :: (HiddenClock DomSys) => (Signal DomSys, Signal DomSys)
My question is: is it possible to change this code slightly, or fiddle with the exact type of withClock
etc., to make this definition of topEntity
typecheck without a type signature on the binding of board
?