I am a new to functional programming. I am scraping a website using Scalpel and I need to extract information from links contained in that website. What I can extrapolate though is just part of the link and I need to add to the String "http://www.google.com/"
to each of these links. I can't do a normal ++
because I don't have a list of String
s.
Here's the code:
{-# LANGUAGE OverloadedStrings #-}
import Text.HTML.Scalpel
main :: IO ()
main = do
res <- scrapeURL "http://www.whateverLink/" scrapeComic
print res
scrapeComic :: Scraper String [[String]]
scrapeComic =
chroots ("ul" @: ["id" @= "research-teachinglist"]) scrapeLink
scrapeLink :: Scraper String [String]
-- This returns me the parts of the links I want
scrapeLink = (attrs "href" "a")
-- I tried this, but it doesn't work
-- scrapeLink = mapM_ ("http://www.google.com/" ++) (attrs "href" "a")
Any ideas?
Thank you
You have
attrs "href" "a" :: Scraper String [String]
and
("http://www.google.com/" ++) :: String -> String
and you'd like to apply the latter to all the String
elements in the former's result list.
First of all, applying it to lists is a matter of
map :: (a -> b) -> [a] -> [b]
so in your case, you have
map ("http://www.google.com/" ++) :: [String] -> [String]
Which gets us one step closer.
Now the next problem is that instead of a pure [String]
value, you have a computation Scraper String [String]
. However, Scraper str
is an instance of Functor
for any choice of str
, in particular, for str ~ String
, i.e. Scraper String
is a Functor
.
What that gives us is a way of applying pure functions to Scraper String
s:
fmap :: (a -> b) -> Scraper String a -> Scraper b
in particular, we have
fmap (map ("http://www.google.com/" ++)) :: Scraper String [String]
leading to
scrapeLink :: Scraper String [String]
scrapeLink = fmap (map ("http://www.google.com/" ++)) (attrs "href" "a")