2017-02-23 20 views
10

Yalnızca wreq ürününün withSession :: (Session -> IO a) -> IO a ürününü kullanıyorum. Devam çizgisini çizgisel olarak değerlendirmek istiyorum, ancak bunun için herhangi bir yol bulamıyorum. Yukarıdaki pasajdaREPL'yi CPS işleviyle nasıl kullanabilirim?

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

nasıl GHCi içinde print res değerlendirebiliriz? Başka bir deyişle, ghci'de Session türünü alabilir miyim?

+0

'withSession' kesmek otomatik hale getirmek bir GHCi oturumu

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

küçük bir kütüphane bu kullanmak işlev tam olarak bir oturum sağlayan işlevdir. "Session" parametresini "withSession" öğesine iletilen işlevin gövdesinde işleyerek geçirirsiniz. Diğer bir deyişle, eğer main = withSession .. 'varsa, eylemi çalıştırmak için ghci komut satırında' main' (veya ': main') yazmanız yeterlidir. Şimdiye kadar "devam çizgisini çizgiye göre değerlendir", bu mantığı kendiniz uygulamak zorundasınız. – user2407038

+0

Vay, harika soru! Gerçekten de, CPS tarzı kütüphane fonksiyonları için GHCi repl'ine yeniden girebilmek güzel olurdu. – chi

cevap

11

Harika bir soru.

GHCi REPL'ye yeniden girebilecek hiçbir yöntemden haberdar değilim, böylece bunu CPS işlevlerinde kullanabiliriz. Belki başkaları bir şekilde önerebilir. Bununla birlikte, bir kesmek önerebilirim. Temel olarak, bu durumda olduğu gibi IO monadına dayanıyorsa, CPS'yi tersine çevirmek için eşzamanlılıktan yararlanabilir. İşte

beygir:

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" 

hızlı bir test:

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