Immagina un linguaggio di programmazione funzionale i cui soli tipi di dati sono scalari numerici e annidamenti arbitrari di array. La lingua non ha alcun mezzo di iterazione illimitata, quindi non sono consentiti:
- loop espliciti (comunque non molto usati senza effetti collaterali)
- ricorsione
- funzioni arbitrarie di prima classe (senza combinatore y)
La lingua tuttavia ha:
- funzioni di alto livello
- ambito less lessico
- flusso di controllo ramificato
- funzioni matematiche e logiche scalari comuni
- qualche semplice costruttore di array come fill (n, x) che crea un array n-element con valori identici x
- soprattutto: un insieme limitato di operatori di ordine superiore che eseguono iterazioni strutturate parallele (come mappa, riduzione, scansione, tutte le coppie).
Per essere più specifici sugli operatori di dati paralleli:
- y = mappa (f, x) => y [i] = f [i]
- y = riduci (f, a, x) => y = f (a, f (y [p [0]], f (y [p [1]], ...))) per alcune permutazioni p
- y = scan (f, a, x) => y [i] = riduci (f, a, y [0 ... i-1])
- y = allpairs (f, x, y) => y [i, j] = f (x [i], y [j])
Potremmo avere anche altri operatori, ma per qualificarli dovrebbero avere un tempo di esecuzione polinomiale, essere implementabili in base a un modello ragionevole di calcolo parallelo dei dati e utilizzare nella maggior parte dello spazio polinomiale.
Esistono ovviamente alcuni costrutti che non possono essere espressi in questa lingua, come:
while f(x) > tol:
x <- update(x)
Cosa possiamo esprimere in questo sistema? Siamo limitati solo ai problemi di ricerca in FP? Possiamo catturare tutti gli algoritmi temporali polinomiali? Inoltre, esiste una serie minima di operatori per questa classe?