11

मेरे पास एक monadic function getRate है:मैं एक मैनाडिक फ़ंक्शन के साथ पैरामैप का उपयोग कैसे कर सकता हूं?

getRate :: String -> IO Double 

मैं इस फ़ंक्शन को स्ट्रिंग की सूची में मैप करना चाहता हूं। आम तौर पर, मैं बस ऐसा करता हूं:

mapM getRate ["foo", "bar"] 

लेकिन चूंकि प्रत्येक कॉल प्राप्त करने के लिए नेटवर्क कॉल करता है, इसलिए मैं मानचित्र को समानांतर करना चाहता हूं ताकि प्रत्येक दर अलग थ्रेड में लाई जा सके (या कम से कम कतारों में फैल जाए)। मैं

parMapM getRate ["foo", "bar"] 

जैसे कुछ के बारे में सोच रहा हूं लेकिन कोई पैरामैम फ़ंक्शन नहीं है और पैरामैप monadic फ़ंक्शंस के साथ काम नहीं करता है।

मैं क्या कर सकता हूं?

उत्तर

6

आपको Control.Concurrent का उपयोग करना चाहिए और एक नियंत्रण के आसपास सिंक्रनाइज़ करना चाहिए। Concurrent.MVar; की तरह कुछ:

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 

इस के कुछ हिस्सों (कांटा, में शामिल होने) अनुक्रमिक देखो। अभ्यास में क्या हो रहा है यह है कि थ्रेड को क्रमशः कांटा में बंद कर दिया जाता है और बदले में प्रत्येक थ्रेड के इंतजार के माध्यम से घूमता है। लेकिन आईओ एक साथ होता है।

ध्यान दें कि यदि आपको विदेशी कार्यों को कॉल करने की आवश्यकता है तो आपको फोर्कियो के बजाय forkOS का उपयोग करना चाहिए।

+0

यह सही है - धन्यवाद! – Bill

6

एक मोनैड-समांतर पैकेज भी है जो mapM :: MonadParallel m => (a -> m b) -> [a] -> m [b] प्रदान करता है। डोनाडपेरल के लिए आईओ इंस्टेंस को देखते हुए यह डोमिनिक के जवाब में वैसे ही करता है।

संबंधित मुद्दे

 संबंधित मुद्दे