Frage

Alle Beispiele, die ich bisher gesehen hat, den Haskell XML-Toolkit verwenden, HXT, runX Anwendungen die Parser auszuführen. runX läuft innerhalb des IO Monade. Gibt es eine Möglichkeit, diese XML-Parser außerhalb des IO zu verwenden? Scheint mir ein reiner Betrieb zu sein, nicht verstehen, warum ich innerhalb IO sein gezwungen.

War es hilfreich?

Lösung

Sie können HXT die mit xread zusammen mit runLA eine XML-Zeichenfolge außerhalb von IO zu analysieren.

xread hat folgenden Typen:

xread :: ArrowXml a => a String XmlTree

Das heißt, Sie es mit jedem Pfeil vom Typ (ArrowXml a) => a XmlTree Whatever komponieren können eine a String Whatever erhalten.

runLA ist wie runX, aber für Dinge des Typs LA:

runLA :: LA a b -> a -> [b]

LA ist eine Instanz ArrowXml.

das alles zusammen zu stellen, die folgende Version von meine Antwort zu Ihrer vorherigen Frage verwendet HXT eine Zeichenfolge wohlgeformte XML beteiligt ohne IO enthält, zu analysieren:

{-# LANGUAGE Arrows #-}
module Main where

import qualified Data.Map as M
import Text.XML.HXT.Arrow

classes :: (ArrowXml a) => a XmlTree (M.Map String String)
classes = listA (divs >>> pairs) >>> arr M.fromList
  where
    divs = getChildren >>> hasName "div"
    pairs = proc div -> do
      cls <- getAttrValue "class" -< div
      val <- deep getText         -< div
      returnA -< (cls, val)

getValues :: (ArrowXml a) => [String] -> a XmlTree (String, Maybe String)
getValues cs = classes >>> arr (zip cs . lookupValues cs) >>> unlistA
  where lookupValues cs m = map (flip M.lookup m) cs

xml = "<div><div class='c1'>a</div><div class='c2'>b</div>\
      \<div class='c3'>123</div><div class='c4'>234</div></div>"

values :: [(String, Maybe String)]
values = runLA (xread >>> getValues ["c1", "c2", "c3", "c4"]) xml

main = print values

classes und getValues sind ähnlich wie die vorherige Version, mit ein paar kleinen Änderungen der erwarteten Eingabe und Ausgabe entsprechen. Der wesentliche Unterschied besteht darin, dass hier verwenden wir xread und runLA statt readString und runX.

Es wäre schön, in der Lage sein, etwas wie ein fauler ByteString in ähnlicher Weise zu lesen, aber soweit ich weiß, dass dies mit HXT derzeit nicht möglich ist.


Ein paar andere Dinge: Sie können Parse-Strings auf diese Weise ohne IO, aber es ist wahrscheinlich besser zu Einsatz runX wann immer Sie können: es Ihnen mehr Kontrolle über die Konfiguration des Parsers gibt, Fehler Nachrichten, etc.

Also: Ich habe versucht, den Code in dem Beispiel einfach zu machen und einfach zu erweitern, aber die Kombinatoren in Control.Arrow und

Andere Tipps

Travis Brown Antwort war sehr hilfreich. Ich will nur hier meine eigene Lösung geben, was ich denke, ein bisschen allgemeiner ist (die gleichen Funktionen verwenden, um nur die problemspezifische Probleme zu ignorieren).

Ich war vorher Unpickling mit:

upIO      :: XmlPickler a => String -> IO [a]
upIO str   = runX $ readString [] str >>> arrL (maybeToList . unpickleDoc xpickle)

, die ich in der Lage war zu dieser ändern:

upPure    :: XmlPickler a => String -> [a]
upPure str = runLA (xreadDoc >>> arrL (maybeToList . unpickleDoc xpickle)) str

ich mit ihm völlig einig, dass dies zu tun gibt Ihnen weniger Kontrolle über die Konfiguration des Parser usw., die unglücklich ist.

scroll top