Я пытаюсь разобраться в HXT, библиотеке Haskell для разбора XML, использующей стрелки. Для моего конкретного случая использования я бы предпочел не использовать deep
, поскольку бывают случаи, когда <outer_tag><payload_tag>value</payload_tag></outer_tag>
отличается от <outer_tag><inner_tag><payload_tag>value</payload_tag></inner_tag></outer_tag>
, но я столкнулся с некоторыми странностями, которые, казалось, должны работать, но не работают.
Мне удалось придумать тестовый пример на основе этот пример из документации:
{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
module Main where
import Text.XML.HXT.Core
data Guest = Guest { firstName, lastName :: String }
deriving (Show, Eq)
getGuest = deep (isElem >>> hasName "guest") >>>
proc x -> do
fname <- getText <<< getChildren <<< deep (hasName "fname") -< x
lname <- getText <<< getChildren <<< deep (hasName "lname") -< x
returnA -< Guest { firstName = fname, lastName = lname }
getGuest' = deep (isElem >>> hasName "guest") >>>
proc x -> do
fname <- getText <<< getChildren <<< (hasName "fname") <<< getChildren -< x
lname <- getText <<< getChildren <<< (hasName "lname") <<< getChildren -< x
returnA -< Guest { firstName = fname, lastName = lname }
getGuest'' = deep (isElem >>> hasName "guest") >>> getChildren >>>
proc x -> do
fname <- getText <<< getChildren <<< (hasName "fname") -< x
lname <- getText <<< getChildren <<< (hasName "lname") -< x
returnA -< Guest { firstName = fname, lastName = lname }
driver finalArrow = runX (readDocument [withValidate no] "guestbook.xml" >>> finalArrow)
main = do
guests <- driver getGuest
print "getGuest"
print guests
guests' <- driver getGuest'
print "getGuest'"
print guests'
guests'' <- driver getGuest''
print "getGuest''"
print guests''
Между getGuest
и getGuest'
я расширяю deep
до правильного числа getChildren
. Полученная функция все еще работает. Затем я факторизую getChildren
за пределами блока do
, но это приводит к сбою результирующей функции. Результат:
"getGuest"
[Guest {firstName = "John", lastName = "Steinbeck"},Guest {firstName = "Henry", lastName = "Ford"},Guest {firstName = "Andrew", lastName = "Carnegie"},Guest {firstName = "Anton", lastName = "Chekhov"},Guest {firstName = "George", lastName = "Washington"},Guest {firstName = "William", lastName = "Shakespeare"},Guest {firstName = "Nathaniel", lastName = "Hawthorne"}]
"getGuest'"
[Guest {firstName = "John", lastName = "Steinbeck"},Guest {firstName = "Henry", lastName = "Ford"},Guest {firstName = "Andrew", lastName = "Carnegie"},Guest {firstName = "Anton", lastName = "Chekhov"},Guest {firstName = "George", lastName = "Washington"},Guest {firstName = "William", lastName = "Shakespeare"},Guest {firstName = "Nathaniel", lastName = "Hawthorne"}]
"getGuest''"
[]
Я чувствую, что это должно быть правильное преобразование для выполнения, но мое понимание стрелок немного шаткое. Я делаю что-то неправильно? Это ошибка, о которой я должен сообщить?
Я использую HXT версии 9.3.1.3 (последняя на момент написания статьи). ghc --version печатает «Славная система компиляции Haskell Glasgow, версия 7.4.1». Я также тестировал на коробке с ghc 7.6.3 и получил тот же результат.
XML-файл имел следующую повторяющуюся структуру (полный файл можно найти в здесь)
<guestbook>
<guest>
<fname>John</fname>
<lname>Steinbeck</lname>
</guest>
<guest>
<fname>Henry</fname>
<lname>Ford</lname>
</guest>
<guest>
<fname>Andrew</fname>
<lname>Carnegie</lname>
</guest>
</guestbook>