Haskell 哈斯克尔';如果我在函数中添加另一行,则SHXT失败
我试图用Haskell的hxt包解析COLLADA文件 我一直做得很好,但我遇到了一个奇怪的错误(或者更可能是我自己的错误) 我有一个箭头,看起来像这样:Haskell 哈斯克尔';如果我在函数中添加另一行,则SHXT失败,haskell,hxt,Haskell,Hxt,我试图用Haskell的hxt包解析COLLADA文件 我一直做得很好,但我遇到了一个奇怪的错误(或者更可能是我自己的错误) 我有一个箭头,看起来像这样: processGeometry = proc x -> do geometry <- atTag "geometry" -< x meshID <- getAttrValue "id" -< geometry meshName <- getAttrValue "name" -<
processGeometry = proc x -> do
geometry <- atTag "geometry" -< x
meshID <- getAttrValue "id" -< geometry
meshName <- getAttrValue "name" -< geometry
mesh <- atTag "mesh" -< geometry
sources <- hasName "source" <<< getChildren -< mesh
positionSource <- hasAttrValue "id" ("-positions" `isSuffixOf`) -< sources
positionArray <- processFloatSource -< positionSource
returnA -< positionArray
这是我正在尝试解析的示例COLLADA文件:
为什么添加一条线会完全改变箭头的结果,而它根本不应该做任何事情;DR:如果要查找两个独立的子元素,请分别调用
getChildren
您的变量sources
不代表所有源元素的列表。相反,它是一个单一的来源。如果您检查源的类型
,您将看到它是XMLTree
。因此,当您对它使用两次hasAttrValue
时,您将寻找一个与这两种情况都匹配的源元素
至于为什么返回什么并不重要:即使没有使用每一行的值,也会执行每一行。事实上,除非您正在使用输出,否则您甚至不必为其指定名称:一行只包含hasAttrValue“id”(isSuffixOf“-normals”)[b]}
实例类别列表箭头,其中
id=ListArrow(\x->[x])
(箭头g)。(ListArrow f)=ListArrow(\x->concatMap g(f x))
实例Arrow ListArrow where
arr f=ListArrow(\x->[f x])
第一个(ListArrow f)=ListArrow(\(a,b)->[(a',b)| a'a->ListArrow(树a)(树a)
hasContent=列表箭头hc,其中
hc cur@(树c_u)=如果内容==c,则[cur]else[]
getContent::ListArrow(树a)a
getContent=ListArrow gc其中
gc(树c))=[c]
--这与问题中的代码有相同的问题
findBothChildrenBad::ListArrow(树字符串)(字符串,字符串)
findBothChildrenBad=proc root->do
--child是根的(单个)子级
小孩
normalSource <- hasAttrValue "id" ("-normals" `isSuffixOf`) -< sources
atTag tag = deep (isElem >>> hasName tag)
data Tree a = Tree a [Tree a]
exampleTree :: Tree String
exampleTree = Tree "root" [Tree "childA" [], Tree "childB" []]
newtype ListArrow a b = ListArrow { runListArrow :: a -> [b] }
instance Category ListArrow where
id = ListArrow (\x -> [x])
(ListArrow g) . (ListArrow f) = ListArrow (\x -> concatMap g (f x))
instance Arrow ListArrow where
arr f = ListArrow (\x -> [f x])
first (ListArrow f) = ListArrow (\(a, b) -> [ (a', b) | a' <- f a ])
getChildren :: ListArrow (Tree a) (Tree a)
getChildren = ListArrow gc where
gc (Tree _ children) = children
hasContent :: Eq a => a -> ListArrow (Tree a) (Tree a)
hasContent content = ListArrow hc where
hc cur@(Tree c _) = if content == c then [cur] else []
getContent :: ListArrow (Tree a) a
getContent = ListArrow gc where
gc (Tree c _) = [c]
-- this has the same problem as the code in the question
findBothChildrenBad :: ListArrow (Tree String) (String, String)
findBothChildrenBad = proc root -> do
-- child is a (single) child of the root
child <- getChildren -< root
-- childA == child, and filter to only cases where its content is "childA"
childA <- hasContent "childA" -< child
-- childB == child, and filter to only cases where its content is "childB"
childB <- hasContent "childB" -< child
-- now the content has to be both "childA" and "childB" -- so we're stuck
childAContent <- getContent -< childA
childBContent <- getContent -< childB
returnA -< (childAContent, childBContent)
-- this is the fixed version
findBothChildren :: ListArrow (Tree String) (String, String)
findBothChildren = proc root -> do
-- childA is a (single) child of the root
childA <- getChildren -< root
-- filter to only cases where its content is "childA"
hasContent "childA" -< childA
-- childB is a (potentially different) child of the root
childB <- getChildren -< root
-- filter to only cases where its content is "childB"
hasContent "childB" -< childB
-- we're not stuck here
childAContent <- getContent -< childA
childBContent <- getContent -< childB
returnA -< (childAContent, childBContent)