11

Ho una funzione monadica getRate:Come posso usare parMap con una funzione monadica?

getRate :: String -> IO Double 

vorrei mappare questa funzione nel corso di un elenco di stringa di. Normalmente, vorrei solo fare:

mapM getRate ["foo", "bar"] 

ma dal momento che ogni chiamata a getRate rende le chiamate di rete, vorrei parallelizzare la mappa in modo che ciascuna aliquota viene recuperato in un thread separato (o almeno sparsi tra le code). Sto pensando a qualcosa di simile

parMapM getRate ["foo", "bar"] 

ma non c'è alcuna funzione parMapM e parMap non funziona con le funzioni monadici.

Cosa posso fare?

risposta

6

È necessario utilizzare Control.Concurrent e sincronizzare attorno a Control.Concurrent.MVar; qualcosa di simile:

fork1 :: (a -> IO b) -> a -> IO (MVar b) 
fork1 f x = 
    do 
    cell <- newEmptyMVar 
    forkIO (do { result <- f x; putMVar cell result }) 
    return cell 

fork :: (a -> IO b) -> [a] -> IO [MVar b] 
fork f = mapM (fork1 f) 

join :: [MVar b] -> IO [b] 
join = mapM takeMVar 

forkJoin :: (a -> IO b) -> [a] -> IO [b] 
forkJoin f xs = (fork f xs) >>= join 

Alcune parti di questo (forchetta, unire) guardare sequenziale. Quello che sta accadendo in pratica è che i fili vengono sparati via via sequenzialmente nella forchetta e rendezvous attraverso l'attesa di ogni thread a turno. Ma l'IO accade contemporaneamente.

Nota: se è necessario chiamare le funzioni esterne, utilizzare forkOS anziché forkIO.

+0

Questo è perfetto - grazie! – Bill