2016-04-04 8 views
1

Ich möchte einen Löschvorgang in Servant ausführen und einen Fehler oder() zurückgeben. Hier ist mein Code:Typen stimmen nicht überein, sollte ich unbedingt liftIO verwenden?

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 

Der Fehler ist:

Couldn't match expected type ‘IO()’ 
       with actual type ‘ExceptT ServantErr m0 a0’ 
    In the expression: throwE err503 
    In a case alternative: _ -> throwE err503 

ich lieber nicht liftIO verwenden, vor jedem Ausdruck, wenn möglich:

del myId = do 
    cn <- liftIO getConnection 
    a <- liftIO $ execute cn "delete from table1 where id = ?" [myId] 
    case a of 
    1 -> return() 
    _ -> throwE err503 

Wie kann ich einen Fehler zurück, dann ?

Antwort

7

Ich denke, Sie werden es nicht vermeiden können. Everthing in einem do-Block muss in der gleichen Monade sein, so mit den anfänglichen

del :: Int -> ExceptT ServantErr IO() 
del myId = liftIO $ do ... 

jede Zeile in IO sein muss. Aber Sie können Dinge auf verschiedene Arten neu anordnen, z. mit einem untergeordneten IO-Block, wo einige Dinge zusammen kommen:

del myId = do 
    a <- liftIO $ do 
    cn <- getConnection 
    execute cn "delete from table1 where id = ?" [myId] 
    case a of 
    1 -> return() 
    _ -> throwE err503 

oder mit Control.Monad.unless, sagt:

del myId = do 
    a <- liftIO $ do 
    cn <- getConnection 
    execute cn "delete from table1 where id = ?" [myId] 
    unless (a == 1) $ throwE err503 

und beliebig vielen anderen Möglichkeiten. Sie sagen nicht, welche getConnection und execute Sie verwenden, aber sind Sie sicher, dass sie nicht bereits MonadIO m => m .. sind? In diesem Fall können Sie die liftIO doch fallen lassen?

Verwandte Themen