import Control.Arrow
Combining lists of Arrows
I believe what you're looking for is a way of combining multiple arrows on the same input to list their output:
list :: Arrow a => [a b c] -> a b [c]
list [] = returnA >>^ const []
list (a:as) = (a &&& list as) >>^ uncurry (:)
(a &&& list as)
returns a pair of the head and the tail, then we post-apply >>^
the pure function uncurry (:) :: (x,[x]) -> [x]
to recombine them.
Let's test it. Here are some things to play with IO arrows. A monad is an arrow, but you have to wrap it into its Kleisli category. runKleisli
unwraps it again so you can run it, but takes me too long to type, so I've used an infix version >$>
to feed it the input:
ask :: Kleisli IO String String
ask = Kleisli $ \xs -> putStrLn xs >> getLine
(>$>) = runKleisli
So now it's easier to interact:
*Main> ask >$> "Hello?"
Hello?
Hello!
"Hello!"
and list
works fine:
*Main> list [ask,ask] >$> "say something!"
say something!
OK
say something!
What do you want me to say?
["OK","What do you want me to say?"]
From [String] to arrow returning [String]
But you want to turn a list of Strings into an arrow that produces lists of Strings.
appList :: Arrow a => (s -> a b c) -> [s] -> a b [c]
appList f xs = list (map f xs)
We can test that with a variant on the ask test:
askRespond xs = Kleisli $ \thx -> do
putStrLn xs
ans <- getLine
putStrLn thx
return ans
So we can see appList
is working the way you want, by making an arrow out of each String, and running each, combining the answers into a string again:
*Main> appList askRespond ["What's your name?","What's your favourite colour?","Would you like some cheese?"] >$> "Thanks."
What's your name?
Andrew
Thanks.
What's your favourite colour?
Green
Thanks.
Would you like some cheese?
Yes - could I have gruyere?
Thanks.
["Andrew","Green","Yes - could I have gruyere?"]
Grabbing multiple tag contents
Now let's apply that to your problem.
First let's make a shorthand to make an arrow out of a string:
textAtTag xs = text <<< atTag xs
Then let's use appList
:
getRowsData = atTag "table"
>>> atTag "row"
>>> appList textAtTag ["study","site"]
I haven't tested that last one - please check!