Смешивание Esqueleto и Persistent в одной и той же функции - PullRequest
0 голосов
/ 05 октября 2018

Возможно, я делаю что-то ужасно глупое, но я бы хотел смешать немного Esqueleto с обычными постоянными запросами в одной и той же функции.

У меня есть функция:

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 ()

, а loadPlanetConstructionQueue имеет подпись(этот выполняет соединение, и поэтому я хотел бы использовать здесь Esqueleto):

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

Это не работает, и я получаю следующую ошибку:

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 ()

Я думаю, что это имеетчто-то делать с разницей между «BackendCompatible SqlBackend backend» и «BaseBackend backend ~ SqlBackend».

Есть ли способ, которым я мог бы заставить это работать?В этом случае я мог бы написать часть selectList с Esqueleto, но в дальнейшем понадобится использовать replace, что не поддерживается Esqueleto (я думаю).

Я не знаю много о Haskell, Постоянный или Эскелето, так что я немного растерялся.

1 Ответ

0 голосов
/ 05 октября 2018

Вы можете добавить BackendCompatible SqlBackend backend в список ограничений handleFactionConstruction, чтобы получить:

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

В общем, ошибка Could not deduce означает, что ваша сигнатура типа является более общей, чем одна изфункции это позволяет.Есть три способа справиться с этим:

  • добавить ограничение, сделав сигнатуру типа более конкретной (как указано выше)
  • сделать вызываемую функцию (loadPlanetConstructionQueue) большеобщее
  • если ни один из перечисленных вариантов невозможен, перепишите код другим способом
...