2008-09-13 12 views
13

Je veux quelque chose qui ressemble à un handle de fichier, mais qui est vraiment soutenu par un tampon en mémoire à utiliser pour les redirections d'E/S. Comment puis-je faire ceci?Comment créer une poignée en mémoire dans Haskell?

+0

Vous peut vouloir revenir sur cette question, il y a une nouvelle réponse que vous devriez voir. –

+0

@Peter Mortensen Il semble que la réponse de John est exactement ce que vous voulez. – PyRulez

Répondre

0

Ce n'est pas possible sans modifier le compilateur. C'est parce que Handle est un type de données abstrait, pas une classe de type.

+0

Merci pour toutes les réponses. Je voulais juste savoir s'il y avait une façon idiomatique d'Haskell de le faire que je ne connaissais pas, alors cette réponse me poursuit. – airportyh

1

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

Voir /libraries/base/IOBase.lhs à partir des sources GHC.

Vous pouvez obtenir le même effet en demandant l'aide du système d'exploitation: créez un fichier temporaire, connectez-y le handle, puis mappez le 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.

3

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 à la réflexion, je pense que mmap pourrait être un mauvais tracé, même si vous l'utilisiez avec l'option anonyme.

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

1

Ceci est en fait un bug dans la conception de la bibliothèque, et celui qui m'a ennuyé, aussi. Je vois deux approches pour faire ce que vous voulez, dont aucune n'est terriblement attirante.

  1. Créer une nouvelle classe de types, faire la poignée actuelle une instance de celui-ci, écrivez une autre instance de faire la chose des données en mémoire, et changer tous vos programmes qui ont besoin d'utiliser cette installation. Peut-être cela est aussi simple que l'importation System.SIO (ou tout ce que 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.

  2. Réécrivez les bibliothèques d'E/S pour les étendre afin de prendre en charge cette opération. Pas anodin, et beaucoup de travail, mais ce ne serait pas un travail particulièrement difficile à faire. Cependant, vous avez un problème de compatibilité avec les systèmes qui n'ont pas cette bibliothèque.

19

Je viens d'écrire une bibliothèque qui fournit ce, appelé "bouton" [hackage]. Vous pouvez l'utiliser pour créer Handle s qui référence/modifier 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)