xml - HXT: How to use output of an arrow as function argument? -
it's difficult give title question… i'm stuck hxt again. understand want do, i'm not sure how make play nicely arrows. here give simplified description of problem.
function foo
takes int
, returns arrow:
foo :: arrowxml => int -> xmltree xmltree
function bar
extracts value of attribute:
bar :: arrowxml => xmltree string
now, need write baz
takes map string
s int
s , returns arrow:
import qualified data.map.lazy m baz :: arrowxml => m.map string int -> xmltree xmltree
logic of baz
: extract value of attribute bar
, in map. if m.lookup
returns just x
, invoke foo x
, otherwise don't (input of arrow goes through unchanged).
afaik every such arrow works filter, in reality arrowxml => xmltree string
type means takes xmltree
, returns (possibly empty) list of string
s. makes me reformulate logic of baz
. given input xmltree
there may many strings, every string should used integer , first found integer should passed foo
. if of them result in nothing
, don't anything.
here i've come with:
baz :: arrowxml => m.map string int -> xmltree xmltree baz m = &&& (bar >>> arr (`m.lookup` m)) >>> arr (uncurry f) f xml nothing = xml f xml (just x) = foo x xml -- compiler says: ^^^ not fast, boy not deduce (arrowxml (->)) arising use of ‘foo’ context (arrowxml a) bound type signature baz :: arrowxml => m.map string int -> xmltree xmltree
not compiler doesn't it, it's difficult reason too.
if reformulate type signatures bit can line pretty well. since have values coming result of arrow in baz
affecting behavior of foo
, values need fed foo
using arrow instead of typical argument. simplifies things lot, i'll recommend creating foo
, foowrapper
handles decision itself. correct types you'd have
{-# language arrows, nomonomorphismrestriction #-} import qualified data.map m import control.arrow.arrowtree import text.xml.hxt.core foo :: arrowxml => (int, xmltree) xmltree foo = undefined bar :: arrowxml => xmltree string bar = undefined
then baz
, should expecting both xmltree
, string
input bar
, it's arrow type needs a (string, xmltree) something
, , here found simplest implement as
baz :: arrowxml => m.map string int -> (string, xmltree) (maybe int, xmltree) baz m = first $ arr $ flip m.lookup m
all arrow doing converting string
lookup on passed in m.map
(assuming given in general environment already). need wrapper feed (maybe int, xmltree)
(int, xmltree)
if , if maybe int
just something
. here arrow syntax comes in handy. since we're making decision here requires our arrow arrowchoice
, so
foowrapper :: (arrowxml a, arrowchoice a) => (maybe int, xmltree) xmltree foowrapper = proc (lkup, tree) -> case lkup of nothing -> returna -< tree v -> foo -< (v, tree)
now can tie overall application nothing more built-in combinators (i discovered returna = arr id
, can use instead, think it's easier understand arr id
)
program :: (arrowxml a, arrowchoice a) => m.map string int -> xmltree xmltree program m = bar &&& arr id >>> -- first split input between bar , arr id baz m >>> -- feed baz m foowrapper -- feed lookup foowrapper can make -- decision on how route xmltree
you don't need worry arrowchoice
constraint, arrowxml
instances brought in scope text.xml.hxt.core
implement arrowchoice
.
if you're curious without proc
notation, simple case statement turned (i think)
foowrapper :: (arrowxml a, arrowchoice a) => (maybe int, xmltree) xmltree foowrapper = arr (\(lkup, tree) -> case lkup of nothing -> left tree v -> right (v, tree)) >>> (returna ||| foo)
the use of |||
forces implement arrowchoice
. while isn't bad, wouldn't call readable , there going on doesn't have actual business logic. once move on more complex situations going explode in complexity well, while proc
notation should remain relatively simple.
Comments
Post a Comment