Mi piacerebbe come possiamo implementare produttore/consumatore in un linguaggio di programmazione funzionale come Haskell? e come sarà diverso da una lingua imperativa? La mia comprensione del linguaggio di programmazione funzionale è primitiva. Qualsiasi aiuto sarà apprezzato.Problema di produttore e consumatore in Haskell?
risposta
Un produttore/consumatore astrazione utilizzando thread preventivi e messaggi inviati attraverso un canale:
import Data.Char
import Control.Concurrent
import Control.Concurrent.Chan
main = do
c <- newChan
cs <- getChanContents c -- a lazy stream of events from eventReader
forkIO (producer c) -- char producer
consumer cs
where
-- thread one: the event producer
producer c = forever $ do
key <- getChar
writeChan c key
-- thread two: the lazy consumer
consumer = mapM_ print . map shift
where shift c | isAlpha c = chr (ord c + 1)
| otherwise = c
Si potrebbe utilizzare un modello simile in Erlang. Thread per rappresentare il consumatore e il produttore, e una condivisione di messaggi tra loro, ognuno agendo in modo asincrono.
Questa risposta descrive come si potrebbe risolvere questo problema in modo imperativo. O più precisamente, come generare funzionalmente un calcolo imperativo che risolve il problema. Mi chiedo se Shiva fosse alla ricerca di una soluzione puramente funzionale. – Conal
Aggiungerò all'eccellente risposta di dons
che il meccanismo sottostante è qualcosa chiamato MVar
ed è un contenitore parallelo obbligatorio per un valore. "Metti" e "prendi" dentro e fuori da un MVar. Ottenere un blocco MVar vuoto, come se ne mettesse uno completo. È contemporaneamente un meccanismo di comunicazione e un meccanismo di sincronizzazione. Credo che sia stato inventato da Arvind come parte del progetto Monsoon/* t. C'è un bellissimo book by Nikhil and Arvind che spiega il loro dialetto pH del parallelo Haskell. Molte delle idee sono state adottate in GHC e il libro merita di essere letto.
Oltre agli approcci di stato menzionati da Norman e Don, puoi anche pensare alla normale applicazione e pigrizia come produttore e consumatore.
Qui è un produttore per i numeri naturali:
nats = [1..]
E qui è un consumatore che calcola le piazze di quei numeri:
squares = map (\x -> x * x) nats
produttori come yield return
in C# o generatori in Python può spesso essere espresso in questo modo: come semplici elenchi pigri in Haskell.
tuttavia i generatori Python possono avere effetti collaterali (a differenza delle liste pure). puoi farlo anche con le liste monadiche, e puoi anche generare quelle con "yield" come in Python con il trasformatore monad GeneratorT dal pacchetto del generatore. – yairchu
Questo è molto vicino a http://stackoverflow.com/questions/1234947/can-producer-consumer-problem-be-solved-without-using-assignment. Hai controllato le soluzioni presentate lì? – nlucaroni