2017-02-23 46 views
10

我剛剛遇到的wreq包。我想逐行評估延續,但我找不到任何方法。如何使用REPL和CPS功能?

import Network.Wreq.Session as S 
withSession $ \sess -> do 
    res <- S.getWith opts sess "http://stackoverflow.com/questions" 
    -- print res 
    -- .. other things 

在上面的代碼中我如何評價在ghci中print res?換句話說,我可以在ghci中獲得Session類型嗎?

+0

的'withSession'功能恰恰是提供會話的功能。通過在傳遞給'withSession'的函數體內操作'sess'參數來獲得會話。換句話說,如果你有'main = withSession ..',那麼只需在ghci提示符下鍵入'main'(或':main')即可運行該操作。至於「逐行評估延續」,你必須自己實現這個邏輯。 – user2407038

+0

哇,很好的問題!能夠重新進入CPS風格的庫函數的GHCi repl確實很好。 – chi

回答

11

精彩的問題。

我知道沒有方法可以重新進入GHCi REPL,以便我們可以在CPS功能中使用它。也許其他人可以建議某種方式。

但是,我可以建議一個黑客。基本上,如果它基於IO monad,就可以利用併發性將CPS從內部轉出。

這裏的黑客:使用在GHCI會議

> sess <- newEmptyMVar :: IO (MVar Session) 
> stop <- newEmptyMVar :: IO (MVar()) 
> forkIO $ withSession $ \s -> putMVar sess s >> takeMVar stop 
> s <- takeMVar sess 
> -- use s here as if you were inside withSession 
> let s =() -- recommended 
> putMVar stop() 
> -- we are now "outside" withSession, don't try to access s here! 

一個小型圖書館,以使自動化的黑客:

data CPSControl b = CPSControl (MVar()) (MVar b) 

startDebugCps :: ((a -> IO()) -> IO b) -> IO (a, CPSControl b) 
startDebugCps cps = do 
    cpsVal <- newEmptyMVar 
    retVal <- newEmptyMVar 
    stop <- newEmptyMVar 
    _ <- forkIO $ do 
     x <- cps $ \c -> putMVar cpsVal c >> takeMVar stop 
     putMVar retVal x 
    s <- takeMVar cpsVal 
    return (s, CPSControl stop retVal) 

stopDebugCps :: CPSControl b -> IO b 
stopDebugCps (CPSControl stop retVal) = do 
    putMVar stop() 
    takeMVar retVal 

testCps :: (String -> IO()) -> IO String 
testCps act = do 
    putStrLn "testCps: begin" 
    act "here's some string!" 
    putStrLn "testCps: end" 
    return "some return value" 

簡單的測試:

> (x, ctrl) <- startDebugCps testCps 
testCps: begin 
> x 
"here's some string!" 
> stopDebugCps ctrl 
testCps: end 
"some return value"