Как создать дескриптор в памяти в Haskell?

Я хочу что-то похожее на дескриптор файла, но на самом деле поддерживается буфером в памяти для использования для перенаправления ввода-вывода. Как я могу это сделать?

Ответы

Ответ 1

Это невозможно без изменения компилятора. Это происходит потому, что Handle является абстрактным типом данных, а не типом.

Ответ 2

Я просто написал библиотеку, которая предоставляет это, называемую "ручкой" [hackage]. Вы можете использовать его для создания Handle, который ссылается/модифицирует ByteString:

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 (FFI). Я начал предлагать использовать mmap, но, во-вторых, я думаю, что mmap может быть неправильным отображением, даже если вы использовали его с анонимной опцией.

Дополнительную информацию о Haskell FFI вы можете найти на wiki haskell.org.

Ответ 4

Это может быть невозможно. GHC, по крайней мере, кажется, требует, чтобы дескриптор имел дескриптор файла ОС, который используется для всех операций чтения/записи/поиска.

См. /libraries/base/IOBase.lhs из источников GHC.

Вы можете получить тот же эффект, заручившись помощью операционной системы: создайте временный файл, подключите к нему дескриптор, а затем сохраните карту для перенаправления ввода-вывода. Таким образом, все дескрипторы ввода/вывода станут видимыми в области отображения памяти.

Ответ 5

На самом деле это ошибка в дизайне библиотеки, и это меня тоже раздражало. Я вижу два подхода к тому, что вы хотите, ни один из которых ужасно привлекателен.

  • Создайте новый typeclass, сделайте текущий дескриптор экземпляром, напишите еще один экземпляр, чтобы сделать объект данных в памяти, и измените все ваши программы, которые должны использовать этот объект. Возможно, это так же просто, как импортировать System.SIO (или все, что вы хотите назвать) вместо System.IO. Но если вы используете пользовательские подпрограммы ввода-вывода в библиотеках, таких как Data.ByteString, там еще предстоит проделать большую работу.

  • Перепишите библиотеки ввода-вывода, чтобы расширить их для поддержки этого. Не тривиально и много работы, но это не было бы особенно трудной задачей. Однако у вас есть проблема совместимости с системами, которые не имеют этой библиотеки.