I'm reading PureScript by Example and got to the part introducing the Reader monad. The example goes like this:
createUser :: Reader Permissions (Maybe User)
createUser = do
permissions <- ask
if hasPermission "admin" permissions
then map Just newUser
else pure Nothing
The confusing part for me is the ask
function. The signature is:
ask :: forall r. Reader r r
It appears as if it creates a Reader out of thin air
When I was reading about the State
monad, it had the same concept with its get
function. And the text explained:
the state is implemented as a function argument hidden by the State monad’s data constructor, so there is no explicit reference to pass around.
I'm guessing this is the key, and the same thing is happening here with the Reader, but I don't understand how it works...
When the above example is run via runReader
, how does the provided value suddenly appear as a result of ask
? The Haskell docs for ask
say: Retrieves the monad environment. But my confusion is from where? The way I see it, a value gets passed to runReader
, gets stored somewhere, and to get it - you call ask
... but that makes no sense.
While the example is PureScript, I'm guessing any Haskell-literate person would also be able to answer, hence the Haskell tag.