return
w Haskell nie to samo jak return
w innych językach. Zamiast tego, co robi return
jest wstrzyknięcie wartości do monady (w tym przypadku IO
). Masz kilka opcji
najprostsze jest wykorzystanie jeśli
scrapePage :: String -> IO()
scrapePage url = do
doc <- fromUrl url
title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText
if (isNothing title) then return() else do
date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc"
if (isNothing date) then return() else do
-- etc
-- make page object and send it to db
return()
Inną opcją jest użycie unless
scrapePage url = do
doc <- fromUrl url
title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText
unless (isNothing title) do
date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc"
unless (isNothing date) do
-- etc
-- make page object and send it to db
return()
ogólny problem polega na tym, że IO
monada nie ma efekty kontrolne (z wyjątkiem wyjątków). Z drugiej strony, można użyć może monada transformator
scrapePage url = liftM (maybe() id) . runMaybeT $ do
doc <- liftIO $ fromUrl url
title <- liftIO $ liftM headMay $ runX $ doc >>> css "head.title" >>> getText
guard (isJust title)
date <- liftIO $ liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc"
guard (isJust date)
-- etc
-- make page object and send it to db
return()
jeśli naprawdę chcesz dostać pełnowartościowy efekty kontroli musisz użyć ContT
scrapePage :: String -> IO()
scrapePage url = runContT return $ do
doc <- fromUrl url
title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText
when (isNothing title) $ callCC ($())
date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc"
when (isNothing date) $ callCC ($())
-- etc
-- make page object and send it to db
return()
Ostrzeżenie: żaden z wyżej kod został testowane, a nawet sprawdzane!
Czy tego chcesz? http://www.haskellforall.com/2012/07/breaking-from-loop.html –