使用Haskell手柄时,我感到有点不安全。即,我正在寻找两个功能(也许它们已经存在,在这种情况下,请原谅我的无知)。

  • 当我获得一个句柄(例如Network.accept返回)时,
    既可读又可写,我希望将它们转换为一对
    只读只写句柄,以便写入只读
    处理将不会键入检查,反之亦然。 (也许可以实现
    这使用幻像类型并包装IO功能吗?)
  • 在并发设置中,我发现多个线程可能写入同一句柄,这带来了非常恶劣的后果。如何通过类型系统(如果可能)防止这种情况发生,或者至少在运行时通过抛出异常来通知这种情况?

  • 任何想法都欢迎。

    最佳答案

    您可能要考虑使用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写入输出,否则将无法访问任何类型的句柄并且永远不会看到其任何端点,因此它无法在任何地方公开或泄漏它们。

    07-24 09:47
    查看更多