Question

Je veux quelque chose qui ressemble à un descripteur de fichier mais qui soit réellement soutenu par un tampon en mémoire à utiliser pour les redirections d'E/S.Comment puis-je faire ceci?

Était-ce utile?

La solution

Ce n'est pas possible sans modifier le compilateur.En effet, Handle est un type de données abstrait, pas une classe de types.

Autres conseils

Je viens d'écrire une bibliothèque qui fournit cela, appelée "knob" [piratage].Vous pouvez l'utiliser pour créer Handles qui référence/modifie un 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)

Si vous pouvez exprimer ce que vous voulez faire en termes d'appels C ou système, vous pouvez utiliser l'interface de fonction étrangère (FFI) de Haskell.J'ai commencé à suggérer d'utiliser mmap, mais après réflexion, je pense que mmap pourrait être un mappage dans le mauvais sens, même si vous l'utilisiez avec l'option anonyme.

Vous pouvez trouver plus d’informations sur Haskell FFI sur le wiki haskell.org.

Cela n'est peut-être pas possible. GHC, au moins, semble nécessiter un handle pour avoir un descripteur de fichier OS utilisé pour toutes les opérations de lecture/écriture/recherche.

Voir /libraries/base/IOBase.lhs provenant des sources GHC.

Vous pourrez peut-être obtenir le même effet en faisant appel à l'aide du système d'exploitation :créez un fichier temporaire, connectez-y le handle, puis mappez la mémoire du fichier pour les redirections d'E/S.De cette façon, toutes les E/S du handle deviendraient visibles dans la section mappée en mémoire.

Il s'agit en fait d'un bug dans la conception de la bibliothèque, et qui m'a également ennuyé.Je vois deux approches pour faire ce que vous voulez, dont aucune n’est terriblement attrayante.

  1. Créez une nouvelle classe de types, faites du handle actuel une instance de celle-ci, écrivez une autre instance pour effectuer la tâche de données en mémoire et modifiez tous vos programmes qui doivent utiliser cette fonctionnalité.C'est peut-être aussi simple que d'importer System.SIO (ou peu importe comment vous voulez l'appeler) au lieu de System.IO.Mais si vous utilisez les routines d'E/S personnalisées dans des bibliothèques telles que Data.ByteString, il y a encore du travail à faire là-bas.

  2. Réécrivez les bibliothèques d'E/S pour les étendre afin de prendre en charge cela.Ce n’est pas anodin et demande beaucoup de travail, mais ce ne serait pas un travail particulièrement difficile à réaliser.Cependant, vous rencontrez un problème de compatibilité avec les systèmes qui ne disposent pas de cette bibliothèque.

Pour ajouter une réponse moderne à cette question, vous pouvez utiliser createPipe depuis System.Process:

createPipe :: IO (Handle, Handle)

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top