Ответ 1
return
в haskell не делает то же самое, что и return
на других языках. Вместо этого, что return
заключается в том, чтобы ввести значение в монаду (в данном случае IO
). У вас есть пара опций
наиболее простым является использование, если
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 ()
другой вариант - использовать 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 ()
общая проблема заключается в том, что монада IO
не имеет управляющих эффектов (кроме исключений). С другой стороны, вы можете использовать трансформатор, возможно, монада
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 ()
Если вы действительно хотите получить полномасштабные эффекты управления, вам нужно использовать 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 ()
ПРЕДУПРЕЖДЕНИЕ: ни один из вышеуказанных кодов не был протестирован или даже не был проверен!