Reputation: 26048
I want to perform a delete operation in Servant and return an error or (). Here's my code:
del :: Int -> ExceptT ServantErr IO ()
del myId = liftIO $ do
cn <- getConnection
a <- execute cn "delete from table1 where id = ?" [myId]
case a of
1 -> return ()
_ -> throwE err503 --compile error
The error is:
Couldn't match expected type ‘IO ()’
with actual type ‘ExceptT ServantErr m0 a0’
In the expression: throwE err503
In a case alternative: _ -> throwE err503
I'd prefer not to use liftIO before each expression if possible:
del myId = do
cn <- liftIO getConnection
a <- liftIO $ execute cn "delete from table1 where id = ?" [myId]
case a of
1 -> return ()
_ -> throwE err503
How can I return an error then?
Upvotes: 1
Views: 160
Reputation: 2909
I think you won't be able to avoid it. Everthing in a do-block must be in the same monad, so with the initial
del :: Int -> ExceptT ServantErr IO ()
del myId = liftIO $ do ...
every line must be in IO
. But you can rearrange things in various ways, e.g. with a subordinate IO block, where some things come together:
del myId = do
a <- liftIO $ do
cn <- getConnection
execute cn "delete from table1 where id = ?" [myId]
case a of
1 -> return ()
_ -> throwE err503
or, with Control.Monad.unless
, say:
del myId = do
a <- liftIO $ do
cn <- getConnection
execute cn "delete from table1 where id = ?" [myId]
unless (a == 1) $ throwE err503
and any number of other ways. You don't say which getConnection
and execute
you are using, but are you sure they are not already MonadIO m => m ..
? In which case you can drop the liftIO
after all?
Upvotes: 7