2017-01-09 10 views
1

Имея следующие модели баз данных, я пытаюсь получить название города (определенное поле из города - связанного объекта) события:Yesod - Ошибка «не соответствует ожидаемому типу» при извлечении данных из базы данных

City json 
    name Text 
    countryId CountryId 
    UniqueCity name 
    deriving Eq 
    deriving Show 
Event 
    title Text 
    description Text 
    date UTCTime 
    cityId CityId 

extractCityName :: EventId -> Text 
extractCityName eventId = do 
event <- runDB $ get404 eventId 
    city <- runDB $ get404 (eventCityId event) 
    x <- cityName city 
    return cityName 

И я имею эту ошибку, даже если эта функция еще не называется (во время компиляции):

Couldn't match expected type `HandlerT site0 IO t0' with actual type `Text' 
    In a stmt of a 'do' block: x <- cityName city 
    In the expression: 
     do { event <- runDB $ get404 eventId; 
      city <- runDB $ get404 (eventCityId event); 
      x <- cityName city; 
      return cityName } 

Можете ли вы помочь мне понять, что случилось с моим кодом?

ответ

2

Это потому, что подпись типа runDB - YesodDB site a -> HandlerT site IO a. Если вы не хотите выполнять действия, связанные с базой данных, в обработчиках Yesod, вам не понадобится runDB. Код для извлечения название города будет выглядеть так:

extractCityName :: EventId -> ReaderT SqlBackend IO (Maybe Text) 
extractCityName eventId = do 
    event <- selectFirst [EventId ==. eventId] [LimitTo 1] 
    case event of 
    Nothing -> return Nothing 
    Just event' -> do 
       city <- getJust (eventCityId $ entityVal event') 
       return $ Just $ cityName city 

Теперь вы можете использовать вышеуказанную функцию в Йесод обработчиков, когда вы на самом деле нужно. Вы можете выполнить сопоставление шаблонов в результатах и ​​отправить страницу 404, если результат Nothing.

+0

Спасибо за ваш быстрый ответ. Теперь функция компилируется, но у меня все еще есть проблема. Как вы сказали, эту функцию можно использовать только в обработчиках Yesod. Вы знаете, что можно сделать, чтобы оно работало и в деревушке? Я задал еще один вопрос с подробными вопросами и кодом: http: //stackoverflow.com/questions/41548361/yesod-function-call-in-hamlet-not-working –