Mixing Esqueleto and Persistent in same function

161 Views Asked by At

I might be doing something horribly stupid, but I would like to mix some Esqueleto with regular Persistent queries in same function.

I have function:

handleFactionConstruction :: (BaseBackend backend ~ SqlBackend,
    PersistStoreWrite backend, PersistQueryRead backend, 
    PersistUniqueRead backend, MonadIO m) =>
    Time -> Entity Faction -> ReaderT backend m ()
handleFactionConstruction date faction = do
    planets <- selectList [ PlanetOwnerId ==. Just (entityKey faction)] []
    queues <- mapM loadPlanetConstructionQueue $ map entityKey planets
    return ()

and loadPlanetConstructionQueue has signature (this one performs a join and therefore I would like to use Esqueleto here):

loadPlanetConstructionQueue :: (MonadIO m, BackendCompatible SqlBackend backend, 
    PersistQueryRead backend, PersistUniqueRead backend) =>
    Key Planet -> ReaderT backend m (Maybe (Entity Planet), [Entity BuildingConstruction

This doesn't work and I get following error:

Could not deduce (BackendCompatible SqlBackend backend)
    arising from a use of ‘loadPlanetConstructionQueue’
  from the context: (BaseBackend backend ~ SqlBackend,
                     PersistStoreWrite backend, PersistQueryRead backend,
                     PersistUniqueRead backend, MonadIO m)
    bound by the type signature for:
               handleFactionConstruction :: forall backend (m :: * -> *).
                                            (BaseBackend backend ~ SqlBackend,
                                             PersistStoreWrite backend,
                                             PersistQueryRead backend,
                                             PersistUniqueRead backend, MonadIO m) =>
                                            Time -> Entity Faction -> ReaderT backend m ()

I think it has something to do with the difference between "BackendCompatible SqlBackend backend" and "BaseBackend backend ~ SqlBackend".

Is there a way I could get this working? In this case I could write selectList portion with Esqueleto, but further down the line there will be need to use replace, which isn't supported by Esqueleto (I think).

I Don't know much about Haskell, Persistent or Esqueleto, so I'm a bit lost here.

1

There are 1 best solutions below

0
On BEST ANSWER

You can add BackendCompatible SqlBackend backend to the constraints list of handleFactionConstruction, to get:

handleFactionConstruction :: (BaseBackend backend ~ SqlBackend,
    BackendCompatible SqlBackend backend
    PersistStoreWrite backend, PersistQueryRead backend, 
    PersistUniqueRead backend, MonadIO m) =>
    Time -> Entity Faction -> ReaderT backend m ()

More generally, a Could not deduce error means that your type signature is more general than one of the functions it allows. There are three ways to handle this:

  • add the constraint, making the type signature more specific (as above)
  • make the function you're calling (loadPlanetConstructionQueue) more general
  • if neither of the above is possible, rewrite the code some other way