Wszystkie przykłady, które widziałem do tej pory przy użyciu zestawu narzędzi Haskell XML, HXT, używają runX
do wykonania analizatora składni. runX
uruchamia się w Monadzie IO. Czy istnieje sposób użycia tego parsera XML poza IO? Wydaje się być dla mnie czystą operacją, nie rozumiem, dlaczego jestem zmuszony przebywać w IO.Uruchamianie Haskell HXT poza IO?
Odpowiedz
Możesz użyć HXT's xread
wraz z runLA
do parsowania łańcucha XML poza IO
.
xread
posiada następujące rodzaje:
xread :: ArrowXml a => a String XmlTree
oznacza to, że można je komponować z dowolnej strzałki typu (ArrowXml a) => a XmlTree Whatever
uzyskać a String Whatever
.
runLA
jest jak runX
, ale do rzeczy typu LA
:
runLA :: LA a b -> a -> [b]
LA
jest instancją ArrowXml
.
Aby to umieścić wszystkie razem, następującą wersję my answer do poprzedniego pytania zastosowania HXT do analizowania ciąg zawierający dobrze uformowane XML bez IO
zaangażowanych:
{-# 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
i getValues
są podobne do poprzedniego wersja z kilkoma niewielkimi zmianami, aby dopasować oczekiwane wejście i wyjście. Główną różnicą jest to, że używamy tutaj xread
i runLA
zamiast readString
i runX
.
Byłoby miło móc przeczytać coś podobnego do leniwego ByteString
w podobny sposób, ale o ile wiem, nie jest to obecnie możliwe z HXT.
Kilka innych rzeczy: ty może ciągi składniowy ten sposób bez IO
, ale to chyba lepiej użyć runX
kiedy można: to daje większą kontrolę nad konfiguracją parser, komunikatów o błędach , itp.
Ponadto: Starałem się, aby kod w tym przykładzie był prosty i łatwy do przedłużenia, ale kombinatory w Control.Arrow
i Control.Arrow.ArrowList
umożliwiają bardziej zwięzłą pracę ze strzałkami, jeśli chcesz. Poniżej jest równoważna definicja classes
, na przykład: odpowiedź
classes = (getChildren >>> hasName "div" >>> pairs) >. M.fromList
where pairs = getAttrValue "class" &&& deep getText
Witaj Travis. To wspaniale. Twoja pomoc jest bardzo przydatna w mojej próbie zmierzenia się z HXT. – Muchin
Travis Brown był bardzo pomocny. Chcę tutaj dodać własne rozwiązanie, które moim zdaniem jest nieco bardziej ogólne (używając tych samych funkcji, po prostu ignorując problemy specyficzne dla problemu).
byłem poprzednio unpickling z:
upIO :: XmlPickler a => String -> IO [a]
upIO str = runX $ readString [] str >>> arrL (maybeToList . unpickleDoc xpickle)
które udało mi się zmienić do tego:
upPure :: XmlPickler a => String -> [a]
upPure str = runLA (xreadDoc >>> arrL (maybeToList . unpickleDoc xpickle)) str
I całkowicie zgadzam się z nim, że robi to daje mniejszą kontrolę nad konfiguracją parser itp., co jest niefortunne.
- 1. Haskell HXT do wyodrębniania listy wartości
- 2. Haskell IO Testowanie
- 3. Haskell IO - rękojeść zamknięta
- 4. Memoizing IO Obliczenia Haskell
- 5. kolejność wykonywania Haskell IO
- 6. Haskell Extensible IO Exceptions?
- 7. Haskell monada: IO [Double] do [IO Double]
- 8. Jak poprawić wydajność Haskell IO?
- 9. Czy można używać Text lub ByteString na HXT w Haskell?
- 10. Konwertuj [IO Int] na IO [Int] w Haskell?
- 11. Haskell ReaderT Env IO płyta montażowa
- 12. Jak połączyć dwa ciągi (IO) w Haskell?
- 13. Funkcja Haskell typu: IO String-> String
- 14. Haskell i akcje niskiego poziomu IO
- 15. Problem z "Looping" IO w Haskell
- 16. Haskell: łowienie niski poziom wyjątki IO
- 17. Haskell: obsługa wyjątków w monadach bez IO
- 18. Wywołanie IO Monada wewnątrz strzałki
- 19. Filtr IO [Maybe String] na IO [String]
- 20. Uruchamianie i kompilowanie 'Hello, World!' w Haskell
- 21. Haskell - Jak mogę korzystać z czystych funkcji wewnątrz funkcji IO?
- 22. Haskell/Persistent-Sqlite: "Brak instancji dla (Control.Monad.Trans.Resource.MonadResource IO)"
- 23. Dlaczego szablon Haskell zezwala na dowolne operacje IO podczas kompilacji?
- 24. Uruchamianie PHP 5.4 Wbudowany serwer WWW poza localhost
- 25. Catching/hijacking stdout w haskell
- 26. Której biblioteki Haskell XML użyć?
- 27. Uruchamianie innych programów w pakiecie programowania Haskell/Linear
- 28. Jak sprawdzić poprawność XML (przez plik XSD) w Haskell?
- 29. kod Skraca który obsługuje IO
- 30. Haskell: lift vs liftIO
Szybki rzut oka sprawia, że wygląda na to, że 'runX' odczytuje plik XML i dlatego jest nieczytelnym IO. – alternative
Myślę, że analizator składni HXT jest parserem "online", tzn. Nie musi czytać całego wejścia, aby rozpocząć produkcję. Plusem tego jest to, że (przynajmniej w zasadzie) może działać ze stałym śladem pamięci, wadą jest to, że musi czytać "fragmenty" sygnału wejściowego na żądanie, więc musi być w IO. –
Ale czy nie można tego łatwo rozwiązać za pomocą leniwego IO? Na przykład, aby uzyskać wysokowydajne analizowanie XML, w tej chwili używam Hexpat (dla ByteStrings i lazy SAX-parsowania.) I polyparse (Poly.Lazy.) Otrzymuję stałe ślady pamięci, szybkie przetwarzanie i * wszystko * parsowanie odbywa się w czystych funkcjach! –