在IO之外运行Haskell HXT?

时间:2010-10-10 18:05:48

标签: haskell hxt

到目前为止,我使用Haskell XML工具包HXT看到的所有示例都使用runX来执行解析器。 runX在IO monad中运行。有没有办法在IO之外使用这个XML解析器?对我来说似乎是一个纯粹的操作,不明白为什么我被迫进入IO。

2 个答案:

答案 0 :(得分:28)

您可以使用HXT的xreadrunLA来解析IO之外的XML字符串。

xread具有以下类型:

xread :: ArrowXml a => a String XmlTree

这意味着您可以使用(ArrowXml a) => a XmlTree Whatever类型的任何箭头撰写它以获得a String Whatever

runLArunX类似,但适用于LA类型的内容:

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

LAArrowXml的实例。

要将所有内容放在一起,以前版本的my answer使用HXT来解析包含格式良好的XML的字符串,而不涉及任何IO

{-# 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

classesgetValues与之前的版本类似,只需进行一些小的更改以适应预期的输入和输出。主要区别在于,我们使用xreadrunLA代替readStringrunX

能够以类似的方式阅读类似懒惰ByteString的内容会很高兴,但据我所知,HXT目前无法实现这一目标。


其他一些事情:你可以以这种方式解析字符串而不用IO,但是最好随时使用runX:它可以让你获得更多控制权解析器的配置,错误消息等

另外:我尝试使示例中的代码简单易用,但Control.ArrowControl.Arrow.ArrowList中的组合使得如果您愿意,可以更简洁地使用箭头。以下是classes的等效定义,例如:

classes = (getChildren >>> hasName "div" >>> pairs) >. M.fromList
  where pairs = getAttrValue "class" &&& deep getText

答案 1 :(得分:1)

Travis Brown的回答非常有帮助。我只是想在这里添加我自己的解决方案,我认为这更通用(使用相同的功能,只是忽略特定于问题的问题)。

我之前曾经发布过:

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

我能够改变这个:

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

我完全同意他的说法,这样做可以减少对解析器等配置的控制,这是不幸的。