Haskell更安全的句柄?

时间:2013-08-08 20:37:18

标签: haskell concurrency io functional-programming

使用Haskell Handles时我觉得有点不安全。也就是说,我正在寻找两个特征(也许它们已经存在,在这种情况下请原谅我的无知)。

  1. 当我获得一个句柄(例如,由Network.accept返回)时,哪个 是可读写的,我希望将它们转换成一对 只读只写处理,以便写入只读 句柄不会打字,反之亦然。 (也许一个人可以实现 这使用幻像类型和IO函数包裹?)
  2. 在并发设置中,我发现多线程可能会写入同一个句柄,这会产生非常严重的后果。如何通过类型系统(如果可能)阻止这种情况,或者至少在运行时通过抛出的异常通知这种情况?
  3. 欢迎任何想法。

2 个答案:

答案 0 :(得分:8)

看起来safer-file-handles库可以满足您的需求。第一部分处理得非常清楚。并发安全性似乎由regions库中的RegionT处理。我根本没有使用它,但它看起来是一种非常常见的方法。

答案 1 :(得分:2)

您可能需要考虑使用network conduit包。它将网络应用程序描述为给出两个“端点”的东西 - 一个接收器将数据推入套接字,一个源从套接字读取数据:

type Application m = AppData m -> m ()

data AppData m Source -- ...
appSource :: AppData m -> Source m ByteStringSource
appSink :: AppData m -> Sink ByteString m ()

这样可以清晰地分离书写和阅读部分。现在,您可以使用这样的源和接收器做任何您喜欢的事情,甚至可以将每个源传递给不同的线程并分别处理输入和输出。当然,每个都只能读取或写入,具体取决于您提供给它的端点。

如果要强制执行单线程处理,可以限制自己将程序组件实现为Conduit ByteString m ByteString。这样的导管可以很容易地变成像Application一样的

asApp :: MonadIO m => Conduit ByteString m ByteString -> Application m
asApp cond ad = appSource ad $= cond $$ appSink ad

但是管道只能使用await请求数据并使用yield写输出,否则无法访问任何类型的句柄并且永远不会看到任何端点,因此它无法公开或把它们泄漏到任何地方。