Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use REPL with CPS function?

Tags:

haskell

I've just encountered withSession :: (Session -> IO a) -> IO a of wreq package. I want to evaluate the continuation line by line, but I can't find any way for this.

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

In above snippet how can I evaluate print res in ghci? In other words, can I get Session type in ghci?

like image 726
jeiea Avatar asked Feb 23 '17 20:02

jeiea


1 Answers

Wonderful question.

I am aware of no methods that can re-enter the GHCi REPL, so that we can use that in CPS functions. Perhaps others can suggest some way.

However, I can suggest an hack. Basically, one can exploit concurrency to turn CPS inside out, if it is based on the IO monad as in this case.

Here's the hack: use this in a GHCi session

> 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!

A small library to automatize the hack:

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"

A quick test:

> (x, ctrl) <- startDebugCps testCps
testCps: begin
> x
"here's some string!"
> stopDebugCps ctrl
testCps: end
"some return value"
like image 98
chi Avatar answered Oct 19 '22 09:10

chi