Search code examples
haskellfunctional-programmingclash

unfamiliar syntax in Haskell / Clash function type signature


while trying to understand the usage of the function withClockResetEnable in Clash.Prelude, I found the signature of this function like this:

withClockResetEnable
  :: forall dom r. KnownDomain dom
  => Clock dom
  -> Reset dom
  -> Enable dom
  -> (HiddenClockResetEnable dom => r)
  -> r

The thing really cause my confusion is this part

  -> (HiddenClockResetEnable dom => r)

which has a comment below: The function with a hidden Clock, hidden Reset, and hidden Enable argument

My confusion is, my limited knowledge tell me, since there is a =>, this line is maybe indicated a type constraint, like the polymorphic type r should have an instance of HiddenClockResetEnable dom, which still makes no sense to me, and I cannot link this line to the comment at all.


Solution

  • This is using the ImplicitParams language option.

    HiddenClockResetEnable is defined as:

    type HiddenClockResetEnable dom = (HiddenClock dom, HiddenReset dom, HiddenEnable dom)
    

    Each of the parts such as HiddenClock is defined like this:

    type HiddenClock dom = (Hidden (HiddenClockName dom) (Clock dom), KnownDomain dom)
    

    We have KnownDomain in the constraints on withClockResetEnable. So what is Hidden?

    type Hidden (x :: Symbol) a = IP x a
    

    The IP class is what the ImplicitParams syntax desugars to. So the original signature means:

    withClockResetEnable
      :: forall dom r. KnownDomain dom
      => Clock dom
      -> Reset dom
      -> Enable dom
      -> ((?clock :: Clock dom, ?reset :: Reset dom, ?enable :: Enable dom) => r)
      -> r
    

    In other words, if you call withClockResetEnable c r e f, and f is some computation that takes these parameters implicitly, then withClockResetEnable will call f with those arguments for the implicit parameters:

    let
      ?clock = c
      ?reset = r
      ?enable = e
    in f