It's very difficult to give good title to this question… I'm stuck with HXT again. I understand what I want to do, but I'm not sure how to make it play nicely with arrows. Here I give simplified description of the problem.
Function foo
takes an Int
and returns an arrow:
foo :: ArrowXml a => Int -> a XmlTree XmlTree
Function bar
extracts value of some attribute:
bar :: ArrowXml a => a XmlTree String
Now, I need to write baz
that takes a map from String
s to Int
s and
returns an arrow:
import qualified Data.Map.Lazy as M
baz :: ArrowXml a => M.Map String Int -> a XmlTree XmlTree
Logic of baz
: extract value of the attribute with bar
and look up it in
the map. If M.lookup
returns Just x
, invoke foo x
, otherwise don't do
anything (input of the arrow goes through unchanged).
AFAIK every such an arrow works as a filter, so in reality ArrowXml a => a
XmlTree String
type means that it takes a XmlTree
and returns (possibly
empty) list of String
s. This makes me reformulate logic of baz
. For
given input XmlTree
there may be many strings, every string should be used
to look up an integer and first found integer should be passed to foo
. If
all of them result in Nothing
, don't do anything.
Here what I've come up with:
baz :: ArrowXml a => M.Map String Int -> a XmlTree XmlTree
baz m = this &&& (bar >>> arr (`M.lookup` m)) >>> arr (uncurry f)
where f xml Nothing = xml
f xml (Just x) = foo x xml
-- compiler says: ^^^ not so fast, boy
Could not deduce (ArrowXml (->)) arising from a use of ‘foo’
from the context (ArrowXml a)
bound by the type signature for
baz :: ArrowXml a => M.Map String Int -> a XmlTree XmlTree
Not only compiler doesn't like it, but it's difficult to reason about too.
baz :: M.Map String Int -> a (String, XmlTree) (Maybe Int, XmlTree)
andfoo :: a (Maybe Int, XmlTree) XmlTree
, or possibly some extra arrow between that gets rid of theMaybe
problem. Then you just havebar &&& arr id >>> baz m >>> foo
, which is much more readable. Basically, if your inputs are coming from arrows, pass those values around using arrows. At this point it's probably going to be worth learning theproc
notation or it'll be even more difficult. – bheklilrproc
notation can help. Thanks for the comment, feel free to add it as an answer if you like. – Mark KarpovArrow*
classes that implement more functionality on top of the basic arrows. I can't say that I feel confident working with arrows yet, but I know the basics of how they work and how to use them. While my answer below looks nice, it took me more than a few minutes to get it working! – bheklilr