Type variable dom0 is ambiguous when using DomainPeriod

I’m using DomainPeriod to create a type based on Index that holds a maximum value for a 1.6 ms timer like this:

type Timeout dom = Index (DivRU (1600000000) (Max 1 (DomainPeriod dom)))

However, when I now try to use this type I get the following error:

    • Couldn't match type: Div
                             (1600000000
                              + (Max
                                   1
                                   (Clash.Signal.Internal.DomainConfigurationPeriod
                                      (KnownConf dom0))
                                 - 1))
                             (Max
                                1
                                (Clash.Signal.Internal.DomainConfigurationPeriod (KnownConf dom0)))
                     with: Div
                             (1600000000
                              + (Max
                                   1
                                   (Clash.Signal.Internal.DomainConfigurationPeriod (KnownConf dom))
                                 - 1))
                             (Max
                                1
                                (Clash.Signal.Internal.DomainConfigurationPeriod (KnownConf dom)))
      Expected: Timeout dom
        Actual: Timeout dom0
      NB: ‘Div’ is a non-injective type family
      The type variable ‘dom0’ is ambiguous
    • In the ambiguity check for ‘timeout’
      To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
      In the type signature: timeout :: (KnownDomain dom) => Timeout dom

This error occurs in the following code snippet:

-- | The duration of @linkTimer@ is 1.6 ms according to the SGMII reference,
--   which means that it has a frequency of 625 Hz. This is the same as 200000
--   cycles of the 125 MHz clock: @1.6*10^−3 / (1 / (125×10^6))@.
--
--   For simulation and testing, this is set to a more reasonable amount of 3
--   to decrease the amount of test values that are needed to trigger a timeout.
timeout :: (KnownDomain dom) => Timeout dom
timeout = if clashSimulation then 3 else maxBound

the result type of timeout cannot be inferred from any input. You can enable the AllowAmbiguousTypes language extension to allow this, in which case you must use a type application or annotation. Or you can add a proxy argument to carry the type.

timeout :: (KnownDomain dom) => Proxy dom -> Timeout dom
1 Like

To expand on Rowan’s answer a bit, the reason result type cannot be inferred is because the “resolved” type of Timeout doesn’t mention dom at all.

In other words, what the type checker might try to do is try and unify Index 5 and Timeout dom. So it will try to answer: given that Timeout dom ~ Index 5, what is dom? And the answer is: there could be many different doms that fit that bill, hence, dom is ambiguous.