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.