假设我们有三个通过HTTP获取数据的同步函数(这些函数可能是内部的API调用):
lookupUser :: String -> IO UserId
lookupUserCity :: UserId -> IO City
lookupLocation :: City -> IO Location
因此,我可以使用monadic composition lookupLocation <=< lookupUserCity <=< lookupUser
来获取用户的位置。但是,由于每个调用都会阻塞,这将阻止程序的其余部分运行。
显然,延续有助于解决这个问题,但我无法找到任何真实的例子。我认为签名会被重写a -> ContT r IO b
,但我不知道如何用这个来实现类似回调的模式。如果有人能告诉我(1)如何写transform :: (a -> IO b) -> (a -> ContT r IO b)
或(2)可以链接到有人这样做的真实例子,我将不胜感激。
答案 0 :(得分:6)
答案 1 :(得分:1)
您可以更频繁地编写transform
:
transform :: Monad m => (a -> m b) -> a -> ContT r m b
transform k = lift . k
这适用于任何monad而不仅仅是IO。但这不是你真正想要的。正如Nikita Volkov所提到的,如果你想要真正的异步编程,延续不是解决方案。
我也推荐使用异步库。
答案 2 :(得分:0)
MFlow Web框架允许这种monadic流程。
它只是阻止等待下一个请求的进程。这可以在普通的IO monad中完成。但是需要额外的效果来管理后退按钮以及在超时后恢复执行状态。