`a` is the type. Num is a `class`.
Here's an example. x is an Int32 and y is an Int64. If they had type Num, then this would be valid:
add :: Num -> Num -> Num -- Not valid Haskell add x y = x + y
add :: Int32 -> Int64 -> ? -- Doesn't compile add x y = x + y
add :: a -> a -> a -- Doesn't compile add x y = x + y
add :: Num a => a -> a -> a add x y = x + y
add :: (a :: Num) -> (a :: Num) -> (a :: Num) -- Not valid Haskell add x y = x + y
`a` is the type. Num is a `class`.
Here's an example. x is an Int32 and y is an Int64. If they had type Num, then this would be valid:
However it's not valid, because you can't add an Int32 and an Int64: But you can add Nums together, as long as they're the same type. You indicate they're the same type by using the same type variable 'a': But now the above complains because you used (+) which belongs to Num, so you have to declare that these `a`s can (+) because they're Nums. And it comes out shorter than your suggestion of putting the constraints afterward: