In che modo IO può causare effetti collaterali nella Programmazione funzionale? [duplicare]

7

Ogni volta che leggo su Haskell, trovo che IO può causare effetti collaterali.

Ma non capisco come lo farebbe?

Intendiamo dire che stiamo scrivendo su un file da una sequenza lazy e un'altra sequenza lenta sta leggendo dallo stesso file?

Questa è l'unica possibilità o c'è qualcosa di fondamentalmente profondo?

    
posta Ashish Negi 10.10.2014 - 14:33
fonte

6 risposte

13

L'ottimizzatore Haskell è autorizzato a manipolare liberamente le chiamate su pure funzioni purché il risultato rimanga lo stesso. Ad esempio, se può vedere che stai chiamando sqrt sullo stesso numero 100 volte, può memorizzare nella cache il valore restituito e chiamarlo solo una volta. Se può vedere che non usi mai effettivamente il risultato di quella funzione, può scegliere di non chiamarlo affatto.

Queste cose non possono essere fatte con IO. Se si legge dallo stdin 100 volte, non si desidera che l'ottimizzatore memorizzi nella cache la prima lettura e riutilizzi quel valore 99 volte in più. Se scrivi sulla console e scarti il valore di ritorno (perché non ti interessa il valore di ritorno di putStrLn ) non vorrai che l'ottimizzatore rimuova del tutto la chiamata di funzione.

Questo è il significato degli effetti collaterali - non dal punto di vista del programmatore (il programmatore intendeva chiaramente che queste cose accadessero) ma dal punto di vista dell'ottimizzatore.

    
risposta data 10.10.2014 - 15:38
fonte
13

Esempio più semplice possibile: stampare "Hello, world!" cambia lo stato del sistema, perché ora la console mostra "Ciao, mondo!", e prima non lo faceva. Non solo hai cambiato lo stato, in realtà è impossibile cambiarlo di nuovo, dal momento che non puoi annullare i caratteri da un terminale! Questo è l'effetto collaterale più grave possibile.

    
risposta data 10.10.2014 - 14:43
fonte
4

Penso che il problema sia che sei un po 'oscuro su cosa si intenda per effetto collaterale. In una funzione pura senza effetti collaterali, la funzione fornisce un risultato che è un risultato diretto dell'input e nient'altro. In una funzione con effetti collaterali, la funzione dipende o cambia lo stato del mondo esterno. Quindi se hai una funzione come square(x) , allora questa è una pura funzione. D'altra parte, se hai una funzione come launch_the_missiles() , allora questo ha un effetto collaterale molto reale (o per un esempio più banale, stampa una pagina).

Così facendo IO cambia lo stato del mondo, cioè l'effetto collaterale

    
risposta data 10.10.2014 - 15:17
fonte
1

Sembra che tu non conosca la definizione CS di un effetto collaterale. Una funzione ha un effetto collaterale se ha un'interazione osservabile con il sistema al di fuori di quella funzione. Di conseguenza, l'output è sempre un effetto collaterale, è possibile osservare un cambiamento nel disco rigido, nella rete, nella console in cui si è verificata l'uscita. L'input è analogamente un effetto collaterale, perché ha un effetto sul calcolo che si verifica nella funzione e può causare un effetto nel sistema esterno, cioè la lettura da una console o da un socket.

    
risposta data 10.10.2014 - 21:50
fonte
0

Gli effetti collaterali significano che, dopo ogni operazione di IO, lo stato del sistema può essere cambiato. Haskell fornisce una chiara divisione del codice Haskell puro e del codice IO.

Vedi: link ;

dal libro: "In Haskell, una funzione non può cambiare qualche stato, come cambiare il contenuto di una variabile (quando una funzione cambia stato, diciamo che la funzione ha effetti collaterali)."

    
risposta data 10.10.2014 - 16:17
fonte
0

Hai mai sentito questo aforisma ?

No man can step in the same river twice. For the second time, it is not the same river, and he is not the same man.

Immagina una delle tue funzioni scrive 1 in /dev/ttyusb0 . In UNIX, questo è "solo un file", ma nella realtà, questo è in realtà il nome di un microcontrollore e scrivendo un 1 attiva una macchina per affettare il pane e affetta 500 pani di pumpernickel. Scrivendo un 1 la prima volta ha causato 500 pagnotte di pumpernickel passare dallo stato "non registrato" allo stato "affettato". L'invio di un altro 1 non ha questo effetto (perché non puoi tornare a "unsliced"!). Non è lo stesso fiume.

Immagina un'altra delle tue funzioni che legge alcuni dati da un flusso. Se si trattasse di un file statico, potresti leggerlo due volte e ottenere gli stessi risultati, ma se invece il tuo stream è un buffer di dati da (ancora un altro) microcontrollore (questo sta monitorando la temperatura di cottura), quindi leggendo il valore più e più volte di nuovo darà risultati diversi man mano che il forno si riscalda o si raffredda. Non è lo stesso uomo.

    
risposta data 11.10.2014 - 03:50
fonte

Leggi altre domande sui tag