7

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?

+0

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

risposta

14

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.

+2

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

6

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.

2

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.

+0

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