2012-01-27 3 views
9

Qualcuno può spiegare o dare qualche risorsa su come funziona la composizione delle funzioni in relazione alla pigrizia?pigrizia e composizione delle funzioni (haskell, erlang)

Ad esempio, come funziona filter (/='W') . map toUpper $ "justaword" in Haskell rispetto alla controparte in erlang che non è pigro?

risposta

13

Ogni volta che viene richiesto un altro carattere (o notifica di fine), il carattere successivo, se presente, viene mappato in maiuscolo, che viene confrontato con "W", consegnato se non uguale.

filter (/= 'W') . map toUpper $ "justaword" 
~> filter (/= 'W') (toUpper 'j' : map toUpper "ustaword") 
~> filter (/= 'W') ('J' : map toUpper "ustaword") 
~> 'J' : filter (/= 'W') (map toUpper "ustaword") 

Ora il primo carattere è disponibile, quindi per domande come null o funzioni come take 1, nessun ulteriore lavoro è fatto. Se vengono richiesti più caratteri dal consumatore, verranno prodotti uno per uno fino al raggiungimento della fine della stringa.

Esempio:

Prelude Data.Char> take 10 . filter (/= 'W') . map toUpper $ repeat 't' 
"TTTTTTTTTT" 

repeat produce un elenco infinito, ma fino a quando solo una parte finita viene consumato, il calcolo termina in un tempo finito. Tuttavia, take 10 . filter (/= 'W') . map toUpper $ repeat 'w' non termina, poiché nessuno dei caratteri prodotti supera lo filter per raggiungere lo take 10.

+0

Grazie per il grande responso :) È possibile scrivere questo codice in un linguaggio rigoroso (senza simulare la pigrizia)? O in un rigoroso languege la lista verrà attraversata due volte, una volta per la mappa e una volta per il filtro, a partire dall'inizio? – Adi

+1

@Adi: sì, ci saranno due percorsi traversali. mappa restituirà un nuovo elenco intermedio, che viene passato al filtro, che passerà oltre e restituirà ancora un altro elenco – newacct

+5

In un linguaggio rigoroso (ansioso, piuttosto), si dovrebbe simulare la pigrizia per ottenere lo stesso comportamento. Alcune lingue lo rendono più facile di altri, preferirei farlo in erlang o in F # piuttosto che in C (e anche se so C, ma quasi nessun'erlang o F # :). Il fatto che ci siano due attraversamenti o uno in una lingua ansiosa dipende dal compilatore. In linea di principio, il filtro e la mappa possono essere fusi, ma in generale il compilatore dovrebbe dimostrare la purezza della funzione mappata e il predicato del filtro per poterlo fare. Quindi nella maggior parte dei casi mi aspetto due attraversamenti, la prova è difficile. –