0
votes

I'm trying to implement the isAdmin function in a similar fashion to these Yesod book examples. The problem is that I want to keep my 'admin' emails in the database, but when I make a database query, isAdmin loses its purity, so I have to return Handler-something IO Bool instead of just Bool. Now, this scraps the very nice syntax sugar in hamlet that allows to do so:

$if isAdmin
    <p ...

Is there a way to still have a pure isAdmin function even if I make a call to the database (I seriously doubt that... by the way, I don't want to pass any parameters to isAdmin)? Or maybe I could still use the $if syntax with the impure function?

P.S.: Currently, I am using a hack in the handler module:

isadmin <- isAdmin

So, I can write in the hamlet corresponding to that handler:

$if isadmin

But it is not universal and I like the first method more.

1
"a pure isAdmin function" -- Terminology nitpicking: something that doesn't take arguments isn't a function. A better wording would be "a pure isAdmin value". If you were talking about the monadic isAdmin you actually have, you could also say "an isAdmin computation". - duplode

1 Answers

3
votes

N.B.: I don't actually know Yesod; this answer is based on general Haskell practice.

Is there a way to still have a pure isAdmin function even if I make a call to the database (I seriously doubt that

It is not possible indeed. Access to an external database must, in one way or another, live in IO; there is no way around it.

Currently, I am using a hack in the handler module:

isadmin <- isAdmin

So, I can write in the hamlet corresponding to that handler:

$if isadmin

That is not a hack; it is one of the standard ways of using the result from a monadic computation. In fact, in the Yesod book page you linked to, right before the isAdmin example you mentioned, there is a snippet that runs a database query and uses the result with $if in a very similar way to what you are doing now:

getBlogR :: Handler Html
getBlogR = do
    -- etc.
    entries <- runDB $ selectList [] [Desc EntryPosted]
    -- etc.
$if null entries
    -- etc.

P.S.:

N.B.: I don't want to pass any parameters to isAdmin

I wonder why you don't want to do so. Perhaps it is because your only need to check whether a single specific user is an admin. In that case, you should consider renaming your computation to isCurrentUserAdmin (or whatever makes sense in your use case). Seeing a name like isAdmin begs the question "who is an admin?", and so it is rather surprising that something with that name doesn't take any arguments.