Haskell Постоянные строки вставки, если их еще нет в базе данных

Я пытаюсь использовать Yesod и настойчивые для создания веб-сайта. Я немного озадачен тем, как использовать постоянный API.

Вот два моих стола

Feed
    url Text
    UniqueFeed url

Subscription
    feed FeedId
    title Text
    UniqueSubscription feed

Я пытаюсь создать фид, если фид с таким URL не существует, а затем добавить подписку на этот фид, если подписка еще не существует.

postFeedR :: Handler RepHtml
postFeedR = do
    url <- runInputPost $ ireq urlField "url"
    title <- runInputPost $ ireq textField "title"

    runDB $ do
        feedId <- insertFeed $ UniqueFeed url
        subscriptionId <- insertSubscription feedId title
        return 

    defaultLayout [whamlet| <p>done|]

insertFeed url = do
    f <- insertBy $ UniqueFeed url
    case f of
        Left (Entity uid _) -> uid
        Right (Key uid) -> do
            (Key uid) <- insert $ Feed url
            return uid

insertSubscription feedId title = do
    s <- insertBy $ UniqueSubscription feedId
    case s of 
        Left (Entity uid _) -> uid
        Right (Key uid) -> do
            (Key uid) <- insert $ Subscription feedId title
            return uid

Я получаю ошибки ниже. Я не понимаю, почему ghc считает, что возвращаемое значение insertFeed и insertSubscription должно быть UniqueFeed и UniqueSubscription. Я хотел бы, чтобы эти функции возвращали ключи вновь созданных записей.

Кроме того, кажется, что я выбрасываю Ключ, который я получаю в каждом из Правых пунктов дела. Почему постоянный возвращает эти ключи. В случае, когда UniqueSubscription отсутствует в базе данных, постоянная не обладает достаточной информацией для создания новой записи подписки, поскольку отсутствует заголовок, которого нет в UniqueSubscription.

Если бы кто-нибудь мог дать мне несколько советов о том, как использовать постоянный API, я был бы очень признателен.

Handler/Home.hs:62:9:
    Kind incompatibility when matching types:
      a0 :: *
      GHandler App App :: * -> *
    Expected type: (a0 -> t0)
                   -> (t0 -> a0 -> m0 a0) -> YesodDB App App (m0 a0)
      Actual type: (a0 -> t0) -> (t0 -> a0 -> m0 a0) -> a0 -> m0 a0
    In a stmt of a 'do' block: feedId <- insertFeed $ UniqueFeed url
    In the second argument of `($)', namely
      `do { feedId <- insertFeed $ UniqueFeed url;
            subscriptionId <- insertSubscription feedId title;
            return }'

Handler/Home.hs:62:9:
    Couldn't match type `YesodPersistBackend App' with `(->)'
    Expected type: (a0 -> t0)
                   -> (t0 -> a0 -> m0 a0) -> YesodDB App App (m0 a0)
      Actual type: (a0 -> t0) -> (t0 -> a0 -> m0 a0) -> a0 -> m0 a0
    In a stmt of a 'do' block: feedId <- insertFeed $ UniqueFeed url
    In the second argument of `($)', namely
      `do { feedId <- insertFeed $ UniqueFeed url;
            subscriptionId <- insertSubscription feedId title;
            return }'

Handler/Home.hs:74:20:
    Couldn't match expected type `Unique Feed'
                with actual type `Database.Persist.Store.PersistValue'
    In the first argument of `return', namely `uid'
    In a stmt of a 'do' block: return uid
    In the expression:
      do { (Key uid) <- insert $ Feed url;
           return uid }

Handler/Home.hs:83:20:
    Couldn't match expected type `Unique Subscription'
                with actual type `Database.Persist.Store.PersistValue'
    In the first argument of `return', namely `uid'
    In a stmt of a 'do' block: return uid
    In the expression:
      do { (Key uid) <- insert $ Subscription feedId title;
           return uid }

1 ответ

Решение

insertBy не принимает ограничение Unique в качестве параметра, getBy является более подходящим.

Но insertUnique - это короткая возможность с результатом Maybe.

postFeedR :: Handler RepHtml
postFeedR = do
    url <- runInputPost $ ireq urlField "url"
    title <- runInputPost $ ireq textField "title"

    runDB $ do
        feedId <- insertFeed url
        _mbSubscriptionId <- insertUnique $ Subscription feedId title
        return ()

    defaultLayout ...

insertFeed url = do
    f <- insertBy $ Feed url
    case f of
        Left (Entity uid _) -> return uid
        Right uid -> return uid
Другие вопросы по тегам