使用基于ReaderT的客户端包装器与Servant客户端

时间:2017-01-10 22:52:03

标签: haskell monad-transformers servant

我正在尝试使用额外的ClientM参数来扩展servant的Token monad,我将用它来调用REST资源。

type TClient a = ReaderT Token ClientM a

然后我为服务方模式匹配定义了以下内容

get :: Token -> ClientM Text
post :: Token -> Int -> ClientM Text
get :<|> post = client (Proxy :: Proxy MyAPI)

现在我的扩展客户端开始玩了。这就是我使用它的方式:

getT :: TClient Text
getT = undefined -- implementation to extract token and call 'get'

postT :: Int -> TClient Text
portT = undefined -- implementation to extract token and call 'post'

queries :: TClient Text
queries = do
    text1 <- postT 5
    text2 <- getT
    return (text1 ++ text2)

--| runReaderT and then runClientM
runTClient :: Token -> TClient a -> ClientEnv -> IO (Either ServantError a)
runTClient token tcm env = runClientM (runReaderT tcm token) env

问题是如何更好地实施getTpostT功能。

我将发布我当前的解决方案,但希望更有经验的haskellers在这里建议更好的

2 个答案:

答案 0 :(得分:1)

以下示例在页面底部使用IO Control Monad Reader我必须实现提升ReaderT的功能

liftReaderT :: m a -> ReaderT r m a
liftReaderT m = ReaderT (const m)

那么我可以像这样详细实现:

getT :: TClient Text
getT = do
    t <- ask
    liftReaderT $ get t

答案 1 :(得分:1)

ReaderT rMonadTrans的一个实例,因此您只需使用lift :: (MonadTrans t, Monad m) => m a -> t m a即可。专门针对有问题的类型,即lift :: ClientM a -> ReaderT Token ClientM a

getT :: Int -> TClient Text
getT = lift . get

postT :: Int -> TClient Text
postT = lift . post