purescript / purescript-prelude

The PureScript Prelude

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Improve documentation for IsSymbol

ursi opened this issue · comments

-- | A class for known symbols
class IsSymbol (sym :: Symbol) where
reflectSymbol :: SProxy sym -> String

As a newcomer who is currently trying to learn this, I don't understand what this is supposed to mean. What is a "known symbol"? I think better documentation would explicitly mention how the compiler will create these instances for you.

I think this will need some workshopping before being ready to put in the module docs, but here's a potential explanation:

A known symbol is a symbol which is "known" to the compiler, in the sense that the compiler can tell you what the sequence of characters in that symbol are. There's a distinction between "known" and "unknown" symbols because having a type variable whose kind is Symbol doesn't guarantee that you can reflect it to the term level via reflectSymbol; you need to have IsSymbol instances for carrying around the actual string data at runtime.

Perhaps simplest example of a case where the compiler can't solve IsSymbol and a Symbol would be unknown is this:

foreign import data Unknown :: Symbol

and so if you write eg

x = reflectSymbol (SProxy :: SProxy Unknown)

you'll get an error that "No type class instance was found for Data.Symbol.IsSymbol Unknown". However that's a slightly weird example as you could argue that you shouldn't even be allowed to write foreign import data Unknown :: Symbol in the first place.

Perhaps a better example might be

test :: forall sym. SProxy sym -> String
test = reflectSymbol

which also doesn't compile because "No type class instance was found for Data.Symbol.IsSymbol sym0". The reason for this is that, with the code as written here, you're trying to return information you don't have. If the above were to compile, then to call test, I'd only have to supply an SProxy. However, by the time I run this code, any information about the phantom type argument of the SProxy has been lost; an SProxy doesn't contain any information at runtime. The purpose of the IsSymbol instance is to carry around the actual string data is carried at runtime, because an SProxy can't do that on its own.