Haskell / Persistent-Sqlite: "Нет экземпляра для (Control.Monad.Trans.Resource.MonadResource IO)"

Я пытался придумать простой и интуитивно понятный способ использования баз данных с Haskell. Я взял этот код из книги Yesod и попытался очистить его, чтобы его было легче понять и использовать.

{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies, OverloadedStrings #-}
{-# LANGUAGE GADTs, FlexibleContexts #-}

import Database.Persist
import Database.Persist.Sqlite (withSqliteConn, runSqlConn, runMigration)
import Database.Persist.TH (share, mkPersist, mkMigrate, sqlSettings, persist)

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persist|
Person                              -- Table name
    name String                     -- String value
    age Int Maybe                   -- Numerical value
|]

updateDB x y = withSqliteConn "data.db" $ runSqlConn $ do
    runMigration migrateAll         -- Creates "Person" table if one doesn't exist
    insert $ Person x $ Just y      -- Inserts values into .db file

main = do
    updateDB "Frank Silver" 40      -- adds name "Frank Silver" and age "40" to data.db file

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

No instance for (Control.Monad.Trans.Resource.MonadResource IO)
      arising from a use of `updateDB'
    Possible fix:
      add an instance declaration for
      (Control.Monad.Trans.Resource.MonadResource IO)
    In a stmt of a 'do' block: updateDB "Frank Silver" 40
    In the expression: do { updateDB "Frank Silver" 40 }
    In an equation for `main': main = do { updateDB "Frank Silver" 40 }

Любые предложения, указывающие мне в правильном направлении, будут оценены.

1 ответ

Решение

С

main = do
    updateDB "Frank Silver" 40

тип updateDB "Frank Silver" 40 предполагается, что IO (), так как это тип по умолчанию для main (должен иметь тип IO a для некоторых a). Но из определения, его тип выводится как MonadRescource m => m a для некоторых a (наверное a = ()но я не уверен) а нет instance MonadResource IO, Так что вам нужно что-то, чтобы преобразовать updateDB для IO действие, нормальный способ сделать это runResourceT, который превращает ResourceT m a в m a (Вот m = IO), так

main = runResourceT $ updateDB "Frank Silver" 40

работает.

Другие вопросы по тегам