我正在遍历表的列表并在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
其中parseTable :: ArrowXml a => a XmlTree (String, String)
将<tr><td>key</td><td>value</td></tr>
解析为(key, value)
元组,并mkThing :: String -> [(String, String)] -> Thing
按name
和info
构建Thing并可能抛出异常(它取决于名称和信息)
如何跳过处理无法构建的东西?如果我保留未捕获的异常,它会以某种方式转换为字符串并进入输出。
答案 0 :(得分:2)
您可以使用catchA
箭头来处理管道内的异常。在这种情况下,parseThing
需要具有更具体的IO感知类型,如IOSArrow
。
要跳过例外,catchA
被赋予none
箭头作为异常处理程序。
以下是完整示例(我从parseThing_aux
中提取parseThing
以提高可读性:
{-# 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
如果您想要压缩表格和标题而不是制作它们的交叉产品,可以将parseThing
更改为
parseThing
= (listA $ deep $ hasName "table") &&& (listA $ deep $ hasName "h3")
>>> arr2 zip >>> unlistA
>>> catchA parseThing_aux none
以无点样式编写parseThing_aux
parseThing_aux
= (getChildren >>> getText) *** listA parseTable
>>^ uncurry mkThing
(您可以通过更改uncurry
来取消mkThing
来消除{{1}}。