2017-02-23 24 views
10

Właśnie napotkałem pakiet withSession :: (Session -> IO a) -> IO a z wreq. Chcę przetestować linię kontynuacji po linii, ale nie mogę znaleźć na to żadnej drogi.Jak korzystać z REPL z funkcją CPS?

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

W powyższym fragmencie jak mogę ocenić print res w ghci? Innymi słowy, czy mogę uzyskać w ghci typ Session?

+0

The 'withSession' funkcja jest właśnie funkcją, która zapewnia sesję. Dostajesz sesję, manipulując parametrem 'sess' w ciele funkcji przekazanej do' withSession'. Innymi słowy, jeśli masz 'main = withSession ..', po prostu wpisz' main' (lub ': main') w zachęcie ghci, aby uruchomić akcję. Na razie "oceń linię kontynuacji po linii", musisz sam wdrożyć tę logikę. – user2407038

+0

Wow, wspaniałe pytanie! Naprawdę byłoby miło móc ponownie wprowadzić replikę GHCi dla funkcji biblioteki w stylu CPS. – chi

Odpowiedz

11

Cudowne pytanie.

Jestem świadomy braku metod, które mogą ponownie wprowadzić REPL GHCi, abyśmy mogli użyć tego w funkcjach CPS. Być może inni mogą sugerować w jakiś sposób.

Mogę jednak zaproponować hakera. Zasadniczo, można wykorzystać współbieżność, aby wyłączyć CPS na lewą stronę, jeśli opiera się na moninie IO, jak w tym przypadku.

Oto Hack: to wykorzystać w sesji 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! 

Mała biblioteka zautomatyzować ten 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" 

szybki test:

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