How can I tell GHC to satisfy a type-level <= constraint if I know it's true at runtime?

After poking around a bit more, I found Justin L's answer to a similar question. He wrapped up his solution into the typelits-witnesses package which I was able to use to solve this problem pretty cleanly:

someMyTypeVal :: Integer -> Maybe SomeMyType
someMyTypeVal n = someNatVal n >>= check
  where check :: SomeNat -> Maybe SomeMyType
        check (SomeNat (_ :: p n)) = case (SNat @1) %<=? (SNat @n) of
          LE Refl -> Just (SomeMyType (MyType @n))
          NLE _ _ -> Nothing

a %<=? b lets us compare two type-level natural numbers and gives us a witness for whether a is less than b (LE) or not (NLE). This gives us the extra constraint in the LE case to return a SomeMyType, but trying to do that in the NLE case would still give us the "can't match ‘1 <=? n’ with ‘'True’" error.

Note the explicit type signature for check—without it, the type of check is inferred as check :: SomeNat -> Maybe a and I would get the following type error:

• Couldn't match type ‘a’ with ‘SomeMyType’
   ‘a’ is untouchable
     inside the constraints: 'True ~ (1 <=? n)

With the explicit type signature everything works and the code is even (reasonably) readable.

Tags:

Haskell