Pergunta

Quero algo que se pareça com um identificador de arquivo, mas que seja realmente apoiado por um buffer na memória para usar para redirecionamentos de E/S.Como posso fazer isso?

Foi útil?

Solução

Não é possível sem modificar o compilador.Isso ocorre porque Handle é um tipo de dados abstrato, não uma typeclass.

Outras dicas

Acabei de escrever uma biblioteca que fornece isso, chamada "knob" [invasão].Você pode usá-lo para criar Handles que fazem referência/modificam um 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)

Se você puder expressar o que deseja fazer em termos de C ou chamadas de sistema, poderá usar a Foreign Function Interface (FFI) de Haskell.Comecei a sugerir o uso do mmap, mas pensando bem, acho que o mmap pode ser um mapeamento errado, mesmo se você o usar com a opção anônima.

Você pode encontrar mais informações sobre o Haskell FFI no wiki haskell.org.

Isto pode não ser possível. GHC, pelo menos, parece exigir um identificador para ter um descritor de arquivo do sistema operacional usado para todas as operações de leitura/gravação/busca.

Ver /libraries/base/IOBase.lhs das fontes do GHC.

Você pode obter o mesmo efeito contando com a ajuda do sistema operacional:crie um arquivo temporário, conecte o identificador a ele e mapeie a memória do arquivo para os redirecionamentos de E/S.Dessa forma, toda a E/S do identificador ficaria visível na seção mapeada de memória.

Na verdade, isso é um bug no design da biblioteca e que também me incomodou.Vejo duas abordagens para fazer o que você deseja, mas nenhuma delas é muito atraente.

  1. Crie uma nova typeclass, faça com que o identificador atual seja uma instância dela, escreva outra instância para fazer os dados na memória e altere todos os seus programas que precisam usar esse recurso.Possivelmente isso é tão simples quanto importar System.SIO (ou como você quiser chamá-lo) em vez de System.IO.Mas se você usar rotinas de E/S personalizadas em bibliotecas como Data.ByteString, há mais trabalho a ser feito lá.

  2. Reescreva as bibliotecas de E/S para estendê-las para suportar isso.Não é trivial e dá muito trabalho, mas não seria um trabalho particularmente difícil de fazer.No entanto, você tem um problema de compatibilidade com sistemas que não possuem esta biblioteca.

Para adicionar uma resposta moderna a esta pergunta, você poderia usar createPipe de System.Process:

createPipe :: IO (Handle, Handle)

https://www.stackage.org/haddock/lts-10.3/process-1.6.1.0/System-Process.html#v:createPipe

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top