尝试使用 proc 和 do 表示法时,haskell 箭头出现混淆

标签 haskell arrows

我一直在尝试编写一些使用箭头的 Haskell 代码的更紧凑版本。

我正在尝试将 xml 转换为元组列表。

运行 tx2 会产生: [("项目 1","项目一",["p1_1","p1_2","p1_3"]),("项目 2","项目二",["p2_1","p2_2"])]

我的代码可以工作,但我不禁想到我不应该像我一样使用那么多的 runLA 调用。我为 getDescgetDispgetPlist 中的每一个调用 runLA。

我想我也许可以使用 procdo 表示法来简化

{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
module Test1 where

import Text.XML.HXT.Arrow.ReadDocument
import Text.XML.HXT.Core

xml = "<top>\
               \<list>\
            \<item>\
                \<desc>Item 1</desc>\
                \<plist>\
                    \<p>p1_1</p>\
                    \<p>p1_2</p>\
                    \<p>p1_3</p>\
                \</plist>\
                \<display>Item One</display>\
            \</item>\
            \<item>\
                \<desc>Item 2</desc>\
                \<plist>\
                    \<p>p2_1</p>\
                    \<p>p2_2</p>\
                \</plist>\
                \<display>Item Two</display>\
            \</item>\
        \</list>\
    \</top>"

tx1 = runLA (xread >>> getChildren >>> hasName "list" >>> getChildren >>> hasName "item") xml
tx2 = map toTuple tx1

toTuple i = let
            desc = getDesc i
            display = getDisp i
            plist = getPlist i
            in (desc, display, plist)

aDesc = getChildren >>> hasName "desc" >>> getChildren >>> getText >>> unlistA
aDisp = getChildren >>> hasName "display" >>> getChildren >>> getText >>> unlistA
aPlist = getChildren >>> hasName "plist" >>> getChildren >>> deep getText

getDesc i = runLA aDesc i
getDisp i = runLA aDisp i
getPlist i = runLA aPlist i

但是当我尝试按如下方式重写 tx2 时:

aToTuple = proc tree -> do
                desc    <-  aDesc  -< tree
            display <-  aDisp -< tree
            plist   <- aPlist -< tree
            returnA -< (desc, display, plist)

tx3 = map (\i -> runLA aToTuple i) tx1

一切都落入一大堆。

转换为 proc/do 表示法时我缺少什么?

谢谢。

最佳答案

您几乎不需要在 HXT 上多次调用 run 函数 箭头以获得您想要的结果。在你的情况下,listA可以用来代替 map runLA 以从箭头获取结果列表。你也可以摆脱 许多 getChildren 调用都使用 />运算符。

你的proc版本的toTuple对我来说看起来不错,但我会重写其余的 您的示例代码为

tx1 = runLA (xread /> hasName "list" /> hasName "item" >>> toTuple) xml

toTuple = proc tree -> do
    desc <- aDesc -< tree
    disp <- aDisp -< tree
    plist <- aPlist -< tree
    returnA -< (desc, disp, plist)


aDesc  = getChildren >>> hasName "desc" /> getText
aDisp  = getChildren >>> hasName "display" /> getText
aPlist = getChildren >>> hasName "plist" >>> listA (getChildren /> getText)

并且不使用箭头表示法,toTuple 可以简单地写为

toTuple = aDesc &&& aDisp &&& aPlist >>> arr3 (,,)

关于尝试使用 proc 和 do 表示法时,haskell 箭头出现混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17951915/

相关文章:

scala - 一步一步/深入解释 : The Power of (Co)Yoneda (preferably in scala) through Coroutines

optimization - GHC 没有优化除主模块以外的模块

list - 用箭头比较列表长度

haskell - 为什么 ArrowApply 在证明与 Monads 等价时是唯一的选择?

haskell - HXT:在 Haskell 中使用 HXT 按位置选择节点?

带箭头的 JavaFX 线/曲线

haskell - 为什么 `((,) r)` 不是 Applicative 的 Functor?

parsing - John Hughes 的确定性 LL(1) 使用 Arrow 和错误进行解析

haskell - Hamlet 自动访问范围内的变量

haskell - 是 (map f) == concatMap (map f . ( :[]))?