我刚刚遇到withSession :: (Session -> IO a) -> IO a过wreq包.我想逐行评估延续,但我找不到任何方法.
import Network.Wreq.Session as S
withSession $ \sess -> do
res <- S.getWith opts sess "http://stackoverflow.com/questions"
-- print res
-- .. other things
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,如何print res在ghci中进行评估?换句话说,我可以Session输入ghci吗?
chi*_*chi 12
精彩的问题.
我知道没有可以重新进入GHCi REPL的方法,所以我们可以在CPS函数中使用它.也许其他人可以提出某种方式.
但是,我可以建议一个黑客.基本上,如果在这种情况下基于IO monad,可以利用并发性将CPS内部转换为内部.
这是hack:在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!
Run Code Online (Sandbox Code Playgroud)
一个小型库,可自动化黑客攻击:
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"
Run Code Online (Sandbox Code Playgroud)
快速测试:
> (x, ctrl) <- startDebugCps testCps
testCps: begin
> x
"here's some string!"
> stopDebugCps ctrl
testCps: end
"some return value"
Run Code Online (Sandbox Code Playgroud)