2

我想在servant 0.5中构建一个简单的rest api示例:

data MyData = MyData { var1 :: Int, var2 :: String } 

app :: Application
app = serve api server

api :: Proxy API
api = Proxy

server :: Server API
server = getItems

getItems :: EitherT ServantErr IO [MyData]
getItems = runEitherT $ do
    aa <- nextRandom -- IO
    bb <- getCurrentTime -- IO
    cc <- getDataFromDb -- IO

    --noteT ??? How??? 
    --MaybeT ??? How??? 

    return $ Just [MyData 111 222] 


startApp :: IO ()
startApp = run 8080 app  

我无法编译它,因为在不同的地方有很多“无法匹配预期类型”的错误。我想这是因为我在“getItems”中混合了 2 个不同的单子。但不仅如此。

4

1 回答 1

4

这里:

getItems :: ExceptT ServantErr IO [MyData]
getItems = runExceptT $ do

runExceptTExceptT ServantErr IO [MyData]到是什么意思IO (Either ServantErr [MyData]。它消除了新ExceptT类型。但你想走另一条路!

您可以使用liftIO将任何IO a动作提升为ExceptT ServantErr IO a动作。它基本上告诉ExceptT包装器“只需将IO操作的结果放在成功的上下文中”。

由于您的整个 do-block 似乎都存在于 中IO,您可以只写:

getItems :: ExceptT ServantErr IO [MyData]
getItems = liftIO $ do
    aa <- nextRandom -- IO
    bb <- getCurrentTime -- IO
    cc <- getDataFromDb -- IO
    ...

而不是单独提升每个IO动作。

其他常见情况:

所有这些函数都非常简单,查看它们的源代码很有启发性。

于 2016-03-25T11:28:04.170 回答