类型不匹配,我是否必须使用liftIO?

时间:2016-04-04 02:43:59

标签: haskell servant

我想在Servant中执行删除操作并返回错误或()。这是我的代码:

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

错误是:

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

如果可能的话,我不希望在每个表达之前使用liftIO:

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

如何返回错误?

1 个答案:

答案 0 :(得分:7)

我认为你无法避免它。 do-block中的everthing必须在同一个monad中,所以使用初始

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

每一行必须在IO。但您可以通过各种方式重新排列内容,例如:有一个从属IO块,有些东西聚集在一起:

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

或与Control.Monad.unless一起说:

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

以及其他许多方式。您没有说明您使用的getConnectionexecute,但是您确定它们还不是MonadIO m => m ..吗?在这种情况下,您可以放弃liftIO吗?