3

我正在迭代表列表,并且在proc我正在使用可能引发异常的函数内部(我无法更改其行为):

parseThing :: ArrowXml a => a XmlTree Thing
parseThing = deep (hasName "table") &&& deep (hasName "h3") >>> proc (table, h3) -> do
  name <- getText <<< getChildren -< h3
  info -< listA parseTable -< table

  returnA $ mkThing name info -- may throw an exception

whereparseTable :: ArrowXml a => a XmlTree (String, String)解析<tr><td>key</td><td>value</td></tr>成一个(key, value)元组并通过 and构建mkThing :: String -> [(String, String)] -> ThingThing并且可能引发异常(它取决于名称和信息)nameinfo

如何跳过处理无法构建的东西?如果我不捕获异常,它会以某种方式转换为字符串并进入输出。

4

1 回答 1

2

您可以使用catchA箭头来处理管道内的异常。在这种情况下parseThing,需要具有更具体的 IO 感知类型,例如IOSArrow.

要跳过异常,catchA 给定none箭头作为异常处理程序。

这是一个完整的示例(为了更好的可读性,我从中提取)parseThing_auxparseThing

{-# LANGUAGE Arrows #-}
import Control.Arrow.ArrowExc (catchA)
import Text.XML.HXT.Core


data Thing = Thing String [(String,String)] deriving Show


main :: IO ()
main = do
  xml <- getContents
  res <- runX $ readString [] xml >>> parseThing
  mapM_ print res


parseThing :: IOSArrow XmlTree Thing
parseThing
  = deep (hasName "table") &&& deep (hasName "h3")
  >>> catchA parseThing_aux none


parseThing_aux :: IOSArrow (XmlTree, XmlTree) Thing
parseThing_aux = proc (table, h3) -> do
    name <- getText <<< getChildren -< h3
    info <- listA parseTable -< table
    returnA -< mkThing name info


parseTable :: ArrowXml a => a XmlTree (String, String)
parseTable = error "Not implemented"


mkThing :: String -> [(String,String)] -> Thing
mkThing n i = Thing n i

旁注1

如果您想压缩表格和标题而不是制作它们的交叉产品,您可以更改parseThing

parseThing
  = (listA $ deep $ hasName "table") &&& (listA $ deep $ hasName "h3")
  >>> arr2 zip >>> unlistA
  >>> catchA parseThing_aux none

旁注2

parseThing_aux用无点风格写会更简洁一点

parseThing_aux
  = (getChildren >>> getText) *** listA parseTable
  >>^ uncurry mkThing

(你可以uncurry通过改变mkThing采取一对消除。)

于 2014-04-20T12:01:56.937 回答