我如何使用REPL和CPS功能? [英] How can I use REPL with CPS function?

查看:139
本文介绍了我如何使用REPL和CPS功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚遇到 withSession ::(Session - > IO a) - > IO a wreq 包。我想逐行评估延续,但我无法找到任何方法。

  import Network.Wreq。 Session作为S 
withSession $ \sess - >
res< - S.getWith opts sesshttp://stackoverflow.com/questions
- print res
- ..其他东西

在上面的代码片段中,如何评估ghci中的 print res ?换句话说,我可以在ghci中获得 Session 类型吗?

解决方案

精彩的问题。



我知道没有方法可以重新输入GHCi REPL,因此我们可以在CPS功能中使用它。也许其他人可以提出一些建议。



然而,我可以提出一个黑客攻击。基本上,如果是基于IO monad,就可以利用并发性将CPS从内部转出来。



下面是黑客攻击:在GHCi会话中使用它

 > sess<  -  newEmptyMVar :: IO(MVar Session)
>停止< - newEmptyMVar :: IO(MVar())
> forkIO $ withSession $ \s - > putMVar sess s>> takeMVar stop
> s< - takeMVar sess
> - 在这里使用,就好像你在里面withSession
>让s =() - 建议
> putMVar stop()
> - 我们现在在Session的外面,不要试图在这里访问!

一个自动化黑客攻击的小型库:

< pre $ 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
putStrLntestCps:begin
act这里有一些字符串!
putStrLntestCps:end
返回一些返回值

A快速测试:

 > (x,ctrl)<  -  startDebugCps testCps 
testCps:begin
> x
这是一些字符串!
> stopDebugCps ctrl
testCps:end
一些返回值


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?

解决方案

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"

这篇关于我如何使用REPL和CPS功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆