Gestione dei problemi di stato nella programmazione funzionale

17

Ho imparato a programmare principalmente da un punto di vista di OOP (come la maggior parte di noi, ne sono sicuro), ma ho passato molto tempo a cercare di imparare come risolvere i problemi in modo funzionale. Ho una buona conoscenza di come risolvere problemi di calcolo con FP, ma quando si tratta di problemi più complicati, mi ritrovo sempre a dover ricorrere a oggetti mutabili. Ad esempio, se sto scrivendo un simulatore di particelle, voglio che gli "oggetti" di particelle con una posizione mutabile da aggiornare. In che modo i problemi intrinsecamente "di stato" vengono in genere risolti utilizzando tecniche di programmazione funzionale?

    
posta Andrew Martin 09.06.2014 - 02:43
fonte

4 risposte

18

I programmi funzionali gestiscono lo stato molto bene, ma richiedono un modo diverso di guardarlo. Per il tuo esempio di posizione, una cosa da considerare è che la tua posizione sia una funzione del tempo anziché un valore fisso . Questo funziona bene per le particelle che seguono un percorso matematico fisso, ma è necessaria una strategia diversa per gestire una modifica nel percorso, ad esempio dopo una collisione.

La strategia di base qui è creare funzioni che accettano uno stato e restituiscono il nuovo stato . Quindi un simulatore di particelle sarebbe una funzione che prende come input una Set di particelle e restituisce una nuova Set di particelle dopo una fase temporale. Quindi chiami ripetutamente quella funzione con il suo input impostato sul suo risultato precedente.

    
risposta data 09.06.2014 - 04:29
fonte
8

Come notato da @KarlBielefeldt, l'approccio funzionale a un tale problema è vederlo come restituire un nuovo stato da uno stato precedente. Le funzioni stesse non contengono alcuna informazione, quindi aggiorneranno sempre lo stato m per indicare n .

Penso che tu trovi questo inefficiente perché presumi che lo stato precedente debba essere tenuto in memoria durante il calcolo del nuovo stato. Si noti che la scelta tra la scrittura di uno stato completamente nuovo o la riscrittura di quella precedente in è un dettaglio di implementazione dal punto di vista di un linguaggio funzionale.

Ad esempio, supponiamo di avere un elenco di un milione di interi e di voler incrementare il decimo di un'unità. Copiare l'intera lista con un nuovo numero in decima posizione è uno spreco, hai ragione; ma è solo il modo concettuale di descrivere l'operazione al compilatore o all'interprete del linguaggio. Il compilatore o l'interprete è libero di prendere la prima lista e sovrascrivere la decima posizione.

Il vantaggio di descrivere l'operazione in questo modo è che il compilatore può ragionare sulla situazione quando molti thread vogliono aggiornare la stessa lista in posizioni diverse. Se l'operazione è descritta come "vai in questa posizione e sovrascrivi quello che trovi", allora è il programmatore, non il compilatore, che è responsabile di assicurarsi che le sovrascritture non collidano.

Con tutto ciò che detto, anche in Haskell esiste una monade di stato che aiuta a modellare situazioni in cui "mantenere lo stato" è una soluzione più intuitiva per un problema. Ma per favore notate anche alcuni problemi che trovate " intrinsecamente stateful, come scrivere su un database "avere soluzioni immutabili come Datomic . Questo può sorprendere finché non capisci che è un concetto, non necessariamente la sua realizzazione.

    
risposta data 09.06.2014 - 16:59
fonte
3

Durante la scrittura di applicazioni grandi e moderatamente grandi, ho spesso trovato utile distinguere tra le sezioni dell'applicazione che sono stateful e quelle che sono stateless.

Le classi / strutture dati nella sezione stateful memorizzano i dati dell'applicazione e le funzioni in questa sezione funzionano con conoscenza implicita dei dati dell'applicazione.

Le classi / strutture dati / funzioni nella sezione stateless sono lì per supportare gli aspetti puramente algoritmici dell'applicazione. Non hanno una conoscenza implicita dei dati dell'applicazione. Funzionano in una natura puramente funzionale. Le parti stateful dell'applicazione potrebbero subire un cambiamento di stato come effetto collaterale delle funzioni di esecuzione nella sezione stateless dell'applicazione.

La parte più difficile è capire quali classi / funzioni inserire nella sezione stateless e quali classi / funzioni inserire nella sezione stateful e avere la disciplina per metterle in file / librerie separati.

    
risposta data 09.06.2014 - 06:02
fonte
3

L'iscrizione al giusto modello mentale aiuta a pensare e gestire meglio lo stato. Nella mia mente, il miglior modello mentale è il libro a fogli mobili . Una volta fatto questo, capirai che la FP si appoggia pesantemente su strutture di dati persistenti che catturano lo stato del mondo e che le funzioni vengono utilizzate per passare a quello stato senza alcuna mutazione.

Rich Hickey illumina queste idee:

sono altri discorsi ma questo dovrebbe indirizzarti nella giusta direzione.

    
risposta data 18.06.2014 - 19:31
fonte

Leggi altre domande sui tag