>
> Check that functions, or at least 'pure' functions, do not depend on variables (unless passed in as arguments, and I haven't looked into linear capabilities if any of felix yet, and how this might interact with call-by-reference issues). A pure function could still declare vars internally I imagine. I guess if there are not potential performance issues here, it seems like it may actually be good to have this as a default, and make impure functions the exception rather than rule, and annotate them with an "impure". If this is achieved, I think it actually puts Felix ahead in purity checking and overall purity compared to most languages out there today, with notable exceptions I can think of being Haskell and variants thereof such as Idris, and of course ATS.
Haskell isn’t pure. Its a lie. Haskell can do I/O hence, functions can have side effects.
Haskell people mistakenly believe monads can provide sequencing. This is incorrect.
Monads express a dependency, but that isn’t sequencing unless you add a evaluation
strategy rules (i.e. imperative programming).
You CAN do functional programming in Felix. But it is a primarily a language with
a special interest in control flow.
Just wait until you meet coroutines :)
Actually .. a small white lie .. procedures. They’re not. They’re actually coroutines.
I just didn’t tell you that.
Ok so linearity: Felix has “uniquness types” They represent first order contracts.
This means the compiler checks if you try to use a variable whose contents have
been moved out. What it doesn’t check is if you “cheat” using pointers. Hence
the type checking is only first order.
In Rust, the checking is second order.
I have doubts about Felix uniquness types. I think Rust got this right
and Felix didn’t.
In Rust, variables are unique by default and you have to explicitly say they’re
sharable. In Felix, they’re sharable by default, and you have to explicitly
say they’re unique.
I suspect the Felix method doesn’t work properly. The problem is that
what C/C++ call “rvalues” or “temporaries” are in fact unique, which is guarranteed
not by Uniq type, but because they’re anonymous. So a uniquness TYPE of values
is the wrong idea. The right idea is that *storage locations* can be unique, that is,
its only variables that matter, because only variables can be shared or not:
expression values cannot be shared, because they’re just the interface
between a function output and another function input, which is always 1-1.
The real problem here is syntax. Expression syntax is totally wrong for the
idea of moving stuff. Notionally a unique variable “goes out of scope” after
it is used so it isn’t visible.Its hard to imagine this visually with existing
language syntax.
Finally, YES it is possible to say functions are pure unless marked impure.
At the moment we have:
fun f …… // unspecifiy purity
pure fun f .. // specified pure
impure fun f // specified impure
For the unspecified one, the compiler could try to determine if its pure
or not. It might fail but that doesn’t matter.
For the pure case, the compiler can again check. If it is definitely
not pure, report an error. But what if the compiler can’t decide?
In that case, the annotation would be dangerous.
It could give a warning if it can’t decide and then assume “impure”.
The issues here are not trivial, especially when it comes to optimisations
that depend on purity.
Part of the problem is that you only get “referential transparency” of
expressions if ALL functions are pure. Already generators make a mess.
—
John Skaller
ska...@internode.on.net