sqlhaskellesqueleto

How to use unless (or when) in an Esqueleto query?


I build a query that joins a few tables and restricts the result further unless one field called IncludeAll equals True.

I'm trying to write it like this

fetch i = runDb . select . from $ \(a, b, c) -> do
  where_ $
        a ^. AId ==. valkey i
    &&. b ^. BField1 ==. a ^. AField2
    &&. c ^. CField1 ==. a ^. AField3
  unless (unValue $ b ^. BIncludeAll) $
    where_ $ b ^. BField2 == c ^. CField2
  return  b

But I get the following error

Couldn't match expected type Bool with actual type Database.Esqueleto.Internal.Language.Value Bool in the first argument of unless

So the unValue somehow does not do the trick. Indeed, something like b ^. BIncludeAll has the type expr (Value a).

Looking at the definition of SqlExpr in the source didn't help me, either:

It's an ADT:

 data SqlExpr a where ...

PS: I use an SQL backend, but ideally that should not matter, right?


Solution

  • unless expects a Bool as its argument, that means a boolean in the "Haskell world". You are passing it unValue $ b ^. BIncludeAll, but b ^. BIncludeAll is not of type Value Bool, it's an SqlExpr (Value Bool), which represents a boolean expression in the "database world". It's an SQL statement that, when evaluated, returns a boolean. The only way to turn SqlExpr (Value Bool) into an actual Value Bool is by calling select $ from $ ....

    As others have noted, the correct way to do this is to just use where_ (b ^. BIncludeAll ||. b ^. BField2 ==. c ^. CField2).