在IO之外运行Haskell HXT?

Muc*_*hin 27 haskell hxt

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

Tra*_*own 28

您可以使用HXT的xread一起runLA解析外部XML字符串IO.

xread 有以下类型:

xread :: ArrowXml a => a String XmlTree
Run Code Online (Sandbox Code Playgroud)

这意味着你可以使用类型的任何箭头组成它(ArrowXml a) => a XmlTree Whatever得到的a String Whatever.

runLA就像runX,但对于类型的东西LA:

runLA :: LA a b -> a -> [b]
Run Code Online (Sandbox Code Playgroud)

LA是一个实例ArrowXml.

综上所述,对前一个问题的回答的以下版本使用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
Run Code Online (Sandbox Code Playgroud)

classes并且getValues与之前的版本类似,只需进行一些小的更改以适应预期的输入和输出.主要区别在于我们使用xreadrunLA不是readStringrunX.

能够以ByteString类似的方式读取类似懒惰的东西会很好,但据我所知,目前HXT不可能.


还有其他一些事情:你可以用这种方式解析字符串IO,但是最好随时使用runX它:它可以让你更好地控制解析器的配置,错误信息等.

另外:我试图使在该示例代码简单,易于扩展,但在组合程序Control.Arrow,并Control.Arrow.ArrowList使其能够与箭头简明得多,如果你喜欢的工作.以下是等效定义classes,例如:

classes = (getChildren >>> hasName "div" >>> pairs) >. M.fromList
  where pairs = getAttrValue "class" &&& deep getText
Run Code Online (Sandbox Code Playgroud)