In Haskell, è una "violazione" della programmazione funzionale interagire con qualcosa che non era un parametro di funzione?

1

Sono sicuro che questo deve essere stato chiesto prima, ma non riesco a trovare da nessuna parte che in realtà risponde alla mia domanda, quindi scuse se ho semplicemente trascurato questo.

Attualmente sto imparando Haskell e mi piace il modo in cui bilancia la flessibilità consentendo la prototipazione rapida con purezza funzionale. Comunque sto cercando di capire le best practice. Una cosa di cui attualmente non sono sicuro è che tu abbia qualcosa di simile al seguente:

worlds :: [Foo] -> [World]
worlds [] = []
worlds fs = map toWorld fs

Questa funzione si basa su una funzione toWorld che sarebbe stata definita altrove. La mia reazione immediata qui è che, poiché stai interagendo con qualcosa di "globale", è "corretto" fare questo? O faresti meglio a passare toWorld nella funzione. Ora, dì che questo era Javascript, ovviamente potresti fare qualcosa del tipo:

function toWorld (foo) {
    console.log('Side effect');
    return foo; // The actual transformation is irrelevant
}

In questo caso, la mia comprensione è che la purezza di worlds dipende semplicemente dalla purezza di toWorld , e con un'implementazione come questa, worlds diventerebbe impuro perché toWorld ha un lato- effetto. Naturalmente in Haskell, dove tali effetti collaterali sono impossibili, si è certi che toWorld sarà sempre puro, quindi questo "fa bene"? (Se ciò ha senso)

Inoltre, dì che toWorld non solo ha preso un foo , ma ha anche preso una costante che ha influenzato la trasformazione. Quindi avevi qualcosa come:

constant = 5

toWorld :: Int -> Foo -> World
toWorld k f = World k f -- Something, again, irrelevant

worlds :: [Foo] -> [World]
worlds [] = []
worlds fs = map (toWorld constant) fs

Questo è ora "impuro"? La costante dovrebbe essere qualcosa che viene sempre passato a worlds ? Perché sicuramente qualcuno potrebbe ridefinire constant in qualcos'altro in fase di runtime e cambiare il funzionamento della funzione?

Spero che tutto ciò abbia un senso. Volevo ottenere alcuni pensieri. Qualsiasi input sarebbe apprezzato, non importa quanto piccolo. Cheers!

    
posta Raiden616 23.09.2018 - 11:52
fonte

3 risposte

6

Is this now "impure"? Should the constant be something that is always passed to worlds?

Nel tuo secondo esempio, la funzione worlds è in realtà una chiusura che fa riferimento alla variabile constant definita nel suo contesto. Questo non influenza la sua purezza perché worlds rispetta ancora la trasparenza referenziale, cioè puoi sostituire qualsiasi invocazione worlds fs dal suo risultato senza cambiare la semantica del programma.

Quindi, dopo aver acquisito il nome globale constant , world è congelato in una pura funzione.

Because surely someone could just redefine constant to something else at runtime and change how the function works?

Non è possibile ridefinire una costante al runtime in Haskell: una volta che una costante è stata compilata, mantiene il suo valore. Non esiste una dichiarazione di assegnazione in Haskell. Non puoi ridefinire una costante nel codice sorgente perché il compilatore si lamenterà: dichiarazioni multiple di ...

Tuttavia, è possibile ridefinire apparentemente una costante nel REPL utilizzando let . Ad esempio:

Prelude> let x = 1
Prelude> x
1
Prelude> f y = y + x
Prelude> f 6
7
Prelude> let x = 3
Prelude> x
3

Ora potresti pensare che x abbia il nuovo valore 3 e questo potrebbe influenzare f , ma in effetti hai definito due x s e il secondo ha ombreggiato il primo. La chiusura f vede ancora il x che è nello scope dove f è definito, quindi ora hai ancora

Prelude> f 6
7

perché f è congelato nel momento in cui è definito.

    
risposta data 23.09.2018 - 21:59
fonte
3

Le costanti, siano esse altre definizioni di funzioni o costanti di dati, non influenzano la purezza o la progettazione funzionale.

    
risposta data 23.09.2018 - 19:56
fonte
1

No, questo non ha nulla a che fare con la purezza della funzione. L'operazione che toWorld esegue potrebbe anche essere definita all'interno di worlds e quindi la domanda non si presenterebbe nemmeno. Il fatto che si tratti di una funzione separata non cambia nulla al riguardo. La purezza della funzione non dipende dai valori dei dati impliciti, non dipende da altre funzioni.

    
risposta data 23.09.2018 - 12:28
fonte

Leggi altre domande sui tag