2013-08-08 5 views
13

Ich fühlte mich ein wenig unsicher bei der Verwendung von Haskell-Griffe. Ich suche nämlich zwei Features (vielleicht sind sie schon da und in diesem Fall bitte vergib mir meine Unwissenheit).Safer Handles in Haskell?

  1. Wenn ich einen Griff erhalten haben (zB zurück von Network.accept), die sowohl lesbar und beschreibbar ist, möchte ich sie in ein Paar konvertieren von read-only und write-only behandelt so, dass das Schreiben auf ein schreibgeschütztes -Handle keine Überprüfung eingibt und umgekehrt. (Vielleicht kann man erreichen, dies mit Phantom-Typen und Wraps um IO-Funktionen?)
  2. Bei einer gleichzeitigen Einstellung fand ich, dass es möglich ist für mehrere Threads auf den gleichen Griff schreiben, was zu ziemlich unangenehmen Folgen führt . Wie kann man das durch das Typsystem verhindern (wenn möglich) oder zumindest über eine ausgelöste Ausnahme während der Laufzeit von einem solchen Fall in Kenntnis setzen?

Jede Idee ist willkommen.

Antwort

2

Sie können das network conduit-Paket in Betracht ziehen. Es beschreibt eine Netzwerkanwendung als etwas, das zwei „Endpunkte“ gegeben ist - ein Waschbecken schiebt Daten in eine Steckdose und eine Quelle, die Daten aus der Fassung lautet:

type Application m = AppData m -> m() 

data AppData m Source -- ... 
appSource :: AppData m -> Source m ByteStringSource 
appSink :: AppData m -> Sink ByteString m() 

Diese trennt sauber das Schreiben und das Lesen Teil. Jetzt können Sie mit einer solchen Quelle und einer Senke machen, was auch immer Sie wollen, und sogar jede einzelne zu einem anderen Thread weiterleiten und Eingang und Ausgang getrennt verarbeiten. Natürlich kann jeder von ihnen nur lesen oder schreiben, abhängig davon, welchen Endpunkt Sie ihm geben.

Wenn Sie die Singlethread-Verarbeitung erzwingen möchten, können Sie sich darauf beschränken, Ihre Programmkomponenten als Conduit ByteString m ByteString zu implementieren. Eine solche Leitung aseily werden kann in eine Application s gedreht wie

asApp :: MonadIO m => Conduit ByteString m ByteString -> Application m 
asApp cond ad = appSource ad $= cond $$ appSink ad 

Aber eine Leitung kann nur verlangen, Daten await mit und schreiben Ausgang yield verwenden, hat sonst keinen Zugang zu jeder Art von Handgriffen und sieht nie eine ihrer Endpunkte , so dass es sie nirgends aussetzen oder auslecken kann.

8

Es sieht aus wie die safer-file-handles Bibliothek tut was Sie wollen. Der erste Teil wird ziemlich klar gehandhabt. Die Parallelität-Sicherheit scheint von RegionT aus der regions Bibliothek behandelt werden. Ich habe das überhaupt nicht benutzt, aber es sieht wie ein ziemlich gewöhnlicher Ansatz aus.