What is the minimal basis for Futhark?
futhark-lang.org
futhark-lang.org
Does anyone know if a language with only high order functions like map, reduce and others could be Turing complete? Probably 80-90% of cases would fit in the schema of some predefined functions like scanl. My intuition is that for some cases you would still need explicit recursion or iteration, for instance if you wanted to loop forever or until a certain condition is met, but perhaps these cases could be modelled with some special high order functions as well, or with explicit infinite recursion as in Rust's 'loop'.
Also, in a high-performance setting, a surprising number of programs do not need recursion (and hence Turing-incompleteness) at all. In the vast majority of the Futhark programs I've written, `while` loops are either not used at all, or used for something fairly simple like an outermost convergence loop (and typically with a iteration bound anyway, so it could be written as a `for` loop with early exit).
"Performance does suffer for nontrivial programs, because the compiler will not understand the algebraic structure of the custom functions, and so will not perform important structural optimisations."
I wonder what it would take for the compiler to understand this algebraic structure? Is this something feasible with more developer resources?
Possible, but not feasible. Map-reduce fusion in particular is difficult when the reduction is expressed non-primitively, because the compiler has to be careful not to duplicate work. The tree reduction is particularly challenging because of the sequential loop that obscures the producer-consumer relationship, but even the chunked reduction would require index analysis to ensure that inlining the map does not duplicate work.
It gets even worse for more complex optimisations. For example, there is no realistic chance that the compiler will be able to efficiently sequentialise any of the hand-written reductions, in those cases where they are nested inside other parallel constructs and their own parallelism is not necessary.
Rust iterators (including the parallel ones in the Rayon library) and C++ ranges are explicitly lazy without being connected to some in-memory structure and so "automatically" have this optimisation (different to Haskell's [a] list type).