Given the type-level list function (from this blog post)
type family Length (xs :: [*]) :: Nat where
Length '[] = 0
Length (_ ': xs) = 1 + Length xs
The value extraction of 'hard-coded' type-list lengths works as expected
t1 :: Integer
t1 = natVal (Proxy :: Proxy (Length '[Int]))
And t1 = 1. However, making a function to get the value from an arbitrary list seems to fail.
t2 :: forall (xs :: [*]). Proxy xs -> Integer
t2 _ = natVal (Proxy :: Proxy (Length xs))
Gives the error
• No instance for (KnownNat (Length xs))
arising from a use of ‘natVal’
Which seems unfortunate but reasonable since only the literals are 'Known'. However, forcing the constraint to be satisfied as follows results in complaints about ambiguous types.
unsafeKnownConstr :: c :~: (KnownNat n :: Constraint)
unsafeKnownConstr = unsafeCoerce Refl
t3 :: forall (xs :: [*]). Proxy xs -> Integer
t3 _ = case Proxy :: Proxy (Length xs) of
p@(_ :: Proxy l) -> case unsafeKnownConstr @(KnownNat l) of
Refl -> natVal @l p
Specifically,
• Could not deduce (KnownNat n0) arising from a use of ‘natVal’
from the context: KnownNat n0 ~ KnownNat (Length xs)
bound by a pattern with constructor:
Refl :: forall k (a :: k). a :~: a,
in a case alternative
...
The type variable ‘n0’ is ambiguous
What is GHC (8.10.4) complaining about here? Alternatively, is there another way to extract these un-Known Nats?