Lauf Haskell HXT außerhalb von IO?
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.
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.