哈斯克尔相当于C#5异步/的await [英] Haskell equivalent of C# 5 async/await
问题描述
我刚刚看了一下新的方式使用等待
和异步
关键字来处理在C#5.0异步函数。 〔实施例从在 C#参考的await :
I just read about the new way to handle asynchronous functions in C# 5.0 using the await
and async
keywords. Examle from the C# reference on await:
private async Task SumPageSizesAsync()
{
// To use the HttpClient type in desktop apps, you must include a using directive and add a
// reference for the System.Net.Http namespace.
HttpClient client = new HttpClient();
// . . .
Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
byte[] urlContents = await getContentsTask;
// Equivalently, now that you see how it works, you can write the same thing in a single line.
//byte[] urlContents = await client.GetByteArrayAsync(url);
// . . .
}
A 任务&LT;字节[]&GT;
重新presents异步任务的未来,将产生类型的值字节[ ]
。使用关键字等待
在工作
将基本上把函数的休息,这将被称为续当任务完成。任何使用功能等待
必须使用关键字异步
并键入任务&LT; A&GT;
是否会返回一个类型 A
。
A Task<byte[]>
represents the Future of an asynchronous task that will generate a value of type byte[]
. Using the keyword await
on a Task
will basically put the rest of the function in a continuation which will be called when the task is done. Any function that uses await
must use the keyword async
and have type Task<a>
if it would return type a
.
因此,行
byte[] urlContents = await getContentsTask;
// Do something with urlContents
将转化为类似
Task newTask = getContentsTask.registerContinuation(
byte[] urlContents => {
// Do something with urlContents
});
return newTask;
这感觉很像一个单子( - 变压器?)。这感觉就像它应该
有一些关系到CPS单子,但也许不是。
This feels a lot like a Monad (-transformer?). It feels like it should have some relation to the CPS monad, but maybe not.
这是我在写作相应的哈斯克尔类型的尝试
Here is my attempt at writing corresponding Haskell types
-- The monad that async functions should run in
instance Monad Async
-- The same as the the C# keyword
await :: Async (Task a) -> Async a
-- Returns the current Task, should wrap what corresponds to
-- a async method in C#.
asyncFunction :: Async a -> Async (Task a)
-- Corresponds to the method Task.Run()
taskRun :: a -> Task a
和上述实施例的一个粗略的翻译
and a rough translation of the above example
instance MonadIO Async -- Needed for this example
sumPageSizesAsync :: Async (Task ())
sumPageSizesAsync = asyncFunction $ do
client <- liftIO newHttpClient
-- client :: HttpClient
-- ...
getContentsTask <- getByteArrayAsync client url
-- getContentsTask :: Task [byte]
urlContents <- await getContentsTask
-- urlContents :: [byte]
-- ...
这将是在Haskell相应的类型?是否有任何哈斯克尔库本(或类似方式)实现的方式来处理异步函数/动作?
Would this be the corresponding types in Haskell? Is there any Haskell library this (or a similar way) implements way to handle asynchronous functions/actions?
另外:你能建立这个使用CPS变压器
Also: Could you build this using the CPS-transformer?
是的, Control.Concurrent.Async
< /一>模块确实解决类似的问题(和具有类似的接口),但在一个完全不同的方式这样做。我想这 Control.Monad.Task
一>将是一个更匹配。什么(我认为)我期待的是期货一元界面的使用延续传递风格幕后
推荐答案
下面是建立在异步$顶部的
工作
单子C $ C>库:
Here's a Task
monad that builds on top of the async
library:
import Control.Concurrent.Async (async, wait)
newtype Task a = Task { fork :: IO (IO a) }
newTask :: IO a -> Task a
newTask io = Task $ do
w <- async io
return (wait w)
instance Monad Task where
return a = Task $ return (return a)
m >>= f = newTask $ do
aFut <- fork m
a <- aFut
bFut <- fork (f a)
bFut
请注意,我没有检查这个单子的法律,所以它可能是不正确的。
Note that I haven't checked the monad laws for this, so it might not be correct.
这是你将如何定义在后台运行的基本任务:
This is how you would define primitive tasks that run in the background:
import Control.Concurrent (threadDelay)
test1 :: Task Int
test1 = newTask $ do
threadDelay 1000000 -- Wait 1 second
putStrLn "Hello,"
return 1
test2 :: Task Int
test2 = newTask $ do
threadDelay 1000000
putStrLn " world!"
return 2
然后你可以将任务
■哪些创建一个新的递延任务准备就绪,可以运行使用不要
标记:
Then you can combine Task
s using do
notation which creates a new deferred task ready to be run:
test3 :: Task Int
test3 = do
n1 <- test1
n2 <- test2
return (n1 + n2)
运行叉TEST3
将酿出工作
并返回未来,你可以随时调用要求的因此,如果必要则阻塞,直到完成。
Running fork test3
will spawn the Task
and return a future which you can invoke at any time to demand the result, blocking if necessary until done.
要表明它的作品,我会做两个简单的测试。首先,我将叉 TEST3
而不苛求其未来只是为了确保它正确派生复合螺纹:
To show that it works, I'll do two simple tests. First, I'll fork test3
without demanding its future just to make sure it spawns the composite thread correctly:
main = do
fork test3
getLine -- wait without demanding the future
这正常工作:
$ ./task
Hello,
world!
<Enter>
$
现在我们可以测试我们的需求,结果会发生什么:
Now we can test what happens when we demand the result:
main = do
fut <- fork test3
n <- fut -- block until 'test3' is done
print n
...这也可以工作:
... which also works:
$ ./task
Hello,
world!
3
$
这篇关于哈斯克尔相当于C#5异步/的await的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!