如何在Haskell中创建一个内存句柄?

19
我想要一个看起来像文件句柄的东西,但实际上是由内存缓冲区支持的,用于I/O重定向。我该怎么做?

您可能希望重新查看此问题,因为有一个新的答案您应该看一下。 - Kevin Vermeer
@Peter Mortensen,看起来John的回答正是你想要的。 - PyRulez
6个回答

21

我刚刚写了一个相关的库,名为“knob” [hackage]。你可以使用它创建引用/修改ByteStringHandle

import Data.ByteString (pack)
import Data.Knob
import System.IO

main = do
    knob <- newKnob (pack [])
    h <- newFileHandle knob "test.txt" WriteMode
    hPutStrLn h "Hello world!"
    hClose h
    bytes <- Data.Knob.getContents knob
    putStrLn ("Wrote bytes: " ++ show bytes)

3
如果您能用C语言或系统调用来表达想要做的事情,那么您可以使用Haskell的Foreign Function Interface(FFI)。我曾建议使用mmap,但仔细思考后,即使您使用了匿名选项,mmap可能也会映射错误。您可以在haskell.org wiki上找到有关Haskell FFI的更多信息。

2

实际上这是库设计上的一个缺陷,也让我很困扰。我看到两种方法可以做到您想要的事情,但都不是很理想。

  1. 创建一个新的类型类,使当前的句柄成为它的实例,编写另一个实例来处理内存中的数据,并更改所有需要使用此功能的程序。可能只需导入 System.SIO(或您想要命名的其他名称)而不是 System.IO 就可以解决问题。但是如果您在诸如 Data.ByteString 等库中使用自定义 I/O 例程,则还需要做更多的工作。

  2. 重写 I/O 库以扩展其支持此功能。并不容易,需要大量的工作,但这并不是特别困难的工作。然而,这将会导致与没有此库的系统存在兼容性问题。


1

这可能是不可能的。至少,GHC 似乎需要一个操作系统文件描述符来执行所有读/写/搜索操作。

请参阅来自 GHC 源的 /libraries/base/IOBase.lhs

您可以通过寻求操作系统的帮助来实现相同的效果:创建一个临时文件,将句柄连接到该文件,然后为 I/O 重定向内存映射该文件。这样,所有句柄 I/O 就会在内存映射部分中变得可见。


1

createPipe的文档中说:“*创建一个用于进程间通信的管道[...]”。”这如何解决OP的问题? - runeks

-3

如果不修改编译器,这是不可能的。这是因为Handle是一个抽象数据类型,而不是一个类型类。


感谢所有的回答。我真的只是想知道是否有一种惯用的 Haskell 方法来做到这一点,所以这个答案对我很有帮助。 - airportyh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接