I'm trying to learn the Persistent Library.
I have two files one with all the types I've defined for my project (diet tracker)
Report.hs
data FoodEntry = FoodEntry { report :: Report
, date :: UTCTime
}
data Report = Report { ...
...
}
and another file used to generate tables
Storage.hs
import Database.Persist.Sql
import qualified Database.Persist.TH as PTH
PTH.share [ PTH.mkPersist PTH.sqlSettings
, PTH.mkMigrate "migrateAll"
]
[PTH.persistLowerCase|
FoodEntry sql=entries
report Report
date UTCTime default=now()
UniqueDate date
Report sql=reports
name Text
reportingUnit Text
nutrients [Nutrient]
Nutrient sql=nutrients
nutrientName Text
nutrientUnit Text
nutrientValue Double Maybe
deriving Show Read
|]
and a file that handles migration
import Control.Monad.Logger
import Database.Persist
import Database.Persist.Postgresql
import Types.Storage
connString :: ConnectionString
connString = "host=127.0.0.1 port=5432 user=postgres dbname=postgres password=password"
runAction
:: (MonadUnliftIO m, IsPersistBackend r,
BaseBackend r ~ SqlBackend) =>
ConnectionString -> ReaderT r (LoggingT m) a -> m a
runAction connectionString action = runStdoutLoggingT
$ withPostgresqlConn connectionString
$ \backend ->
runReaderT action backend
migrateDB :: IO ()
migrateDB = runAction connString (runMigration migrateAll)
In my [ProjectName.hs]
file which main
calls on
args <- parseArgs -- args - optparse-applicative
if generateDB args == Just True
then migrateDB
else case (...) of
... -> ...
... -> ...
(s, n, p, Just True) -> undefined
for the last case I want to add the user entry to the database.
I also have a function searchReport
that consumes s
, n
& p
to returns a Report
type.
I want to do something like this
insertReport :: (MonadIO m) => UTCTime -> Report -> SqlPersistT m (Key FoodEntry)
insertReport time report' = insert (FoodEntry report' time)
do date' <- Data.Time.Clock.getCurrentTime :: IO UTCTime
report' <- searchReport s n p :: IO Report
insertReport $ date' report'
But there are (AFAIK) two problem with this
The type of
Report.FoodEntry
would not match the typeStorage.FoodEntry
I could write a function that'd convert one to the other but I wonder if there's a better way of doing that.If I were to test the function in that do block like this
(s, n, p, Just True) -> insertReport undefined undefined
I get error
• Couldn't match type ‘ReaderT Database.Persist.Sql.Types.Internal.SqlBackend m0’ with ‘IO’ Expected type: IO () Actual type: persistent-2.9.2:Database.Persist.Sql.Types.SqlPersistT m0 (persistent-2.9.2:Database.Persist.Class.PersistEntity.Key Types.Storage.FoodEntry)