As part of my journey in understanding singletons I have tried to bridge the gap between compile time safety, and lifting runtime values into that dependent typ
You can do this with an existentially quantified type variable, as in @Alec’s answer, or equivalently by rewriting in continuation-passing style. The trick is to give fromList a continuation (function) that’s polymorphic in the size of the Vec; then, within the continuation, you have access to a type variable representing the size:
data Vec n a where
Nil :: Vec Z a
Cons :: a -> Vec n a -> Vec (S n) a
deriving instance (Show a) => Show (Vec n a)
fromList :: [a] -> (forall n. Vec n a -> r) -> r
fromList [] k = k Nil
fromList (x : xs) k = fromList xs $ \ xs' -> k (Cons x xs')
-- fromList [1, 2, 3] show == "Cons 1 (Cons 2 (Cons 3 Nil))"
You can’t know the actual value of n, because it’s not available at compile time.
If you replace your Nat with the one from GHC.TypeLits, I think you can get a KnownNat constraint for n by creating a SomeNat from the runtime length using fromJust (someNatVal (fromIntegral (length xs))), then get back the actual length value at runtime with natVal. I’m not really familiar with how to do it, and it might require the ghc-typelits-natnormalise plugin, but it might be a starting point.