Are you referring to Symbol in class IsSymbol (sym :: Symbol)? If so, sym is a type variable, and Symbol is the kind of that type variable. The only valid arguments to this type class are things that are of kind Symbol, which are type level strings.
This class is “magic” in that it is automatically solved by the compiler, so yes, all symbols effectively have an instance for IsSymbol by virtue of the compiler being able to generate the dictionary on the fly. A function doesn’t work because there is nothing for the compiler to solve. You would be unable to abstract over it like what inj is doing.
@milesfrain I think that in theory you could have an implication between these constraints (Cons => IsSymbol) which you are asking for - a working approximation could be:
class (Cons l a t r, IsSymbol l) ⇐ Kons l a t r
x ∷ ∀ l a t r. Kons l a t r ⇒ SProxy l → a → Variant r
x = inj
Cons could imply IsSymbol… but they are in some sens “unrelated” because Cons doesn’t use reflectSymbol or share any “laws” with IsSymbol so it probably won’t happen
Another part of the reason why Cons and IsSymbol are not related is to ensure that Cons has no data (it’s purely a type-level guarantee, with unsafe foreign code supporting function implementations), while IsSymbol has to include the data for reflectSymbol in its instance, as mentioned above. Of course they are most commonly used together.
p.s. Don’t forget instance kons :: (Cons l a t r, IsSymbol l) => Kons l a t r