I am just starting to learn Haskell and focus on how to handle exceptions in Scotty.
I have the main function below. It receives a JSON POST, converts it to a Haskell data record, grabs the postgres connection pool from the configuration reader, and then inserts the record into the database.
create :: ActionT Text ConfigM ()
create = do
a :: Affiliate <- jsonData
pool <- lift $ asks pool
_ <- liftIO $ catchViolation catcher $ withResource pool $ \conn ->
PgSQL.execute conn "INSERT INTO affiliate (id, network, name, status) VALUES (?, ?, ?, ?)"
(slug a, network a, name a, status a)
let s = fromStrict $ unSlug $ slug a
text $ "Created: " `T.append` s
where
catcher e (UniqueViolation "mykey") = throw e
catcher e _ = throw e
This function compiles fine, but when I change UniqueViolation to return text, it does not compile.
catcher e (UniqueViolation "mykey") = text "Error"
Indicated compilation error:
Couldn't match type ‘ActionT e0 m0 ()’ with ‘IO Int64’
Expected type: PgSQL.SqlError -> ConstraintViolation -> IO Int64
Actual type: PgSQL.SqlError
-> ConstraintViolation -> ActionT e0 m0 ()
In the first argument of ‘catchViolation’, namely ‘catcher’
In the expression: catchViolation catcher
catchViolation comes from Database.PostgreSQL.Simple.Errors and has the following link:
catchViolation :: (SqlError -> ConstraintViolation -> IO a) -> IO a -> IO a
I know that part of the problem is getting IO Int64 from PgSQL.execute, but ActionT is from a trap, but not sure how to resolve types or a more idiomatic way to do this.