Imagine uma linguagem de programação funcional cujos únicos tipos de dados são escalares numéricos e aninhamentos arbitrários de matrizes. O idioma não possui meios de iteração ilimitada, portanto, o seguinte não é permitido:
- loops explícitos (pouco uso sem efeitos colaterais)
- recursão
- funções arbitrárias de primeira classe (sem combinador y)
A linguagem, no entanto, possui:
- funções de nível superior
- lexicamente, deixe ligações
- fluxo de controle de ramificação
- funções matemáticas e lógicas escalares comuns
- algum construtor de matriz simples como fill (n, x), que cria uma matriz de n elementos com valores idênticos x
- o mais importante: um conjunto restrito de operadores de ordem superior que executam iterações estruturadas paralelas (como mapear, reduzir, varrer, todos os pares).
Para ser mais específico sobre os operadores paralelos de dados:
- y = mapa (f, x) => y [i] = f [i]
- y = reduzir (f, a, x) => y = f (a, f (y [p [0]], f (y [p [1]], ...))) para alguma permutação p
- y = varredura (f, a, x) => y [i] = redução (f, a, y [0 ... i-1])
- y = allpairs (f, x, y) => y [i, j] = f (x [i], y [j])
Também poderíamos ter outros operadores, mas para qualificá-los, eles deveriam ter um tempo de execução polinomial, ser implementável sob algum modelo razoável de computação paralela de dados e usar no máximo espaço polinomial.
Obviamente, existem algumas construções que não podem ser expressas nessa linguagem, como:
while f(x) > tol:
x <- update(x)
O que podemos expressar neste sistema? Estamos limitados apenas a procurar problemas no FP? Podemos capturar todos os algoritmos de tempo polinomial? Além disso, existe algum conjunto mínimo de operadores para essa classe?