Preoccupazioni per la valutazione lazy e le strutture di dati infiniti

2

Sto cercando di capire come funziona la valutazione pigra perché ho intenzione di implementare provare per implementarlo nel linguaggio di programmazione che sto sviluppando (so che non è è la cosa migliore da fare (cercare di implementare qualcosa che non capisci nemmeno) ma è una buona lezione attraverso il mondo dei linguaggi funzionali e simili), quindi stavo leggendo il documento A Gentle Introduction to Haskell .

Presto ho incontrato il paragrafo sulla non rigidità delle funzioni di Haskell e la possibilità di creare strutture di dati teoreticamente infinite, come mostrato in questo esempio:

numsfrom n = 1 : numsfrom (n + 1)

squares = map (^ 2) (numsfrom 0)

Ora, take 5 squares restituirebbe [0, 1, 4, 9, 16] , giusto? Bene, il mio problema è capire come lo farebbe.

Per prima cosa, questo è quello che ho capito della valutazione pigra:

lazy = lambda x, y: x or y

Assumendo Python non era severo, se passassi a lazy 1 e 5 ** 1000000 il secondo parametro non sarebbe stato valutato, ma sarebbe stato valutato se avessi passato False come primo argomento, perché% ilor avrebbe quindi richiesto.

Quindi quando si chiama take 5 squares , squares deve essere valutato: map è chiamato con (^ 2) e (numsfrom 0) come argomenti; Ma poiché map usa il suo secondo argomento, verrà valutato numsfrom 0 , iniziando un ciclo infinito.

Non riesco a capire come restituirà map se sta valutando un ciclo infinito e cosa restituirebbe. Qualcuno può spiegarmi per favore?

    
posta user6245072 14.08.2016 - 17:25
fonte

2 risposte

3

Hai il concetto fondamentale assolutamente corretto. Il problema è che non lo stai applicando su una scala sufficientemente grande.

In Haskell, tutto (o abbastanza vicino per gli scopi di questa domanda e risposta) si comporta come or in Python (e in molte, molte lingue). Compreso, diciamo, "Prendi il prossimo elemento dell'elenco".

Quindi quando chiami numsfrom , infatti, il risultato di numsfrom non viene creato immediatamente e restituito. Viene prodotto secondo necessità su base elemento-per-elemento. La funzione numsfrom può essere parzialmente valutata, pezzo dopo pezzo, in quanto è necessario il risultato. Poiché map non richiede un numero infinito di elementi, non vi è alcun ciclo infinito in corso. Questo è simile agli iteratori che credo in Python.

Come nota a margine, non dovrebbe numsfrom essere numsfrom n = n : numsfrom (n + 1) ? Mi sembra che il tuo numsfrom generi una lista infinita di 1 s.

    
risposta data 14.08.2016 - 18:04
fonte
3

Il trucco è che qualsiasi costruttore di dati in Haskell è pigro (a meno che non sia annotato altrimenti ). Nel tuo caso, il costruttore della lista

(:) :: a -> [a] -> [a]

Quindi quando valutate take 5 squares (ricordate che gli elenchi di Haskell sono elenchi concatenati), valutate i primi cinque costruttori di (:) , ma il resto viene mantenuto come un thunk non valutato.

    
risposta data 14.08.2016 - 17:51
fonte

Leggi altre domande sui tag