#haskell
#haskell
Вопрос:
Я в 99% случаев использую Haskell / Scalpel scraper для извлечения тысяч файлов .gz пакетами и сохранения их локально на моем клиенте.
Теперь я пытаюсь взять фрагментированные [[String]]
файлы и перевести их в IO, чтобы их можно было сохранить.
Я использую import Network.HTTP.Req
.
-- This is the argument for the downloadFiles function
chunkLinks :: IO [[String]]
chunkLinks = fmap (chunksOf 10) filterNonGz
-- THIS IS WHAT YOU EXECUTE
downloadFile :: (MonadHttp m) => String -> m ()
downloadFile url = do
-- Pull them into memory
contents <- req GET (https (T.pack url)) NoReqBody bsResponse mempty
-- Get the filename itself
let fileName = head $ reverse $ T.splitOn "/" (T.pack url)
-- Write them to the client (the filename will be the url)
liftIO $ BSS.writeFile (dataDir (T.unpack fileName)) (responseBody contents)
dataDir = "./Data/LODES/"
eatChunks :: (MonadHttp m) => m [()]
eatChunks = do
(wtf :: [[String]]) <- liftIO $ (take (5) <$> chunkLinks)
fmap concat $ liftIO $ mapM (liftIO . mapConcurrently (liftIO . downloadFile)) wtf
Я получаю сообщение об ошибке downloadFile
в последней строке.
Ошибка:
• Could not deduce (MonadHttp IO)
arising from a use of ‘downloadFile’
from the context: MonadHttp m
bound by the type signature for:
eatChunks :: forall (m :: * -> *). MonadHttp m => m [()]
at /private/var/folders/70/kchtzk4j0hs398f95ywd78x00000gn/T/ghc-mod39229/UsCensusDataLodesScraper39228-2281.hs:195:1-37
Пожалуйста, извините за liftIO
разбросанные по. Они предпринимают отчаянные попытки заставить это работать…
Кто-нибудь знает, что делать дальше?
Для справки, вывод chunkLinks
выглядит следующим образом:
[["https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2002.csv.gz","https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2003.csv.gz","https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2004.csv.gz","https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2005.csv.gz","https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2006.csv.gz","https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2007.csv.gz","https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2008.csv.gz","https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2009.csv.gz","https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2010.csv.gz","https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2011.csv.gz"], ...etc.
Комментарии:
1. Единственным экземпляром
MonadHttp
являетсяReq
. Способ выполненияReq
действия — этоrunReq
. Таким образом, вместо того, чтобы использоватьliftIO
для повышения вашегоdownloadFile
отIO
до чего-то, что не может сработать, потому чтоdownloadFile
не являетсяIO
действием, используйтеrunReq
для понижения вашегоdownloadFile
от чего-то доIO
.2. Я пробовал это, но, очевидно, я все еще делаю что-то не так:
fmap concat $ mapM (mapConcurrently (runReq downloadFile)) wtf
3. Пытаюсь использовать defaultHttpConfig:
fmap concat $ mapM (mapConcurrently (runReq . (defaultHttpConfig downloadFile))) wtf