I'm just starting out learning Haskell and am stuck on how to handle exceptions in Scotty.
I have the basic function below. It gets a JSON POST, converts it in to a Haskell data record, gets a hold of a postgres connection pool from the config reader and then inserts the record in to 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 --text "Error"
catcher e _ = throw e
This function compiles ok but when I change the UniqueViolation to return text it fails to compile.
catcher e (UniqueViolation "mykey") = text "Error"
The compilation error given is:
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 the Database.PostgreSQL.Simple.Errors and has the below signiture:
catchViolation :: (SqlError -> ConstraintViolation -> IO a) -> IO a -> IO a
I know part of the issue is it's getting the IO Int64 from PgSQL.execute but a ActionT from the catcher but not sure how to resolve the types or a more idiomatic way of doing this.