Like my last post on ATS , this is far from a full-fledged tutorial, but I think it will nonetheless be instructive to students of ATS.
Linear types are a relatively unfamiliar feature to most programmers; Rust is the only mainstream language that has them, but ATS gives the programmer finer control of how linear types, allowing the programmer to construct their own linear types in much the same way as ordinary types in an ML.
Linear types in this example accomplish essentially what is accomplished in Rust - they allow us to safely skirt garbage collection where performance is absolutely critical.
To again use a "real world" example from polyglot, suppose we wish to count the number of lines in a file.
// Takes as an argument a string containing the full path to a file. fun line_count(s: string): int = let var ref = fileref_open_opt(s, file_mode_r) in case+ ref of | ~None_vt() => (println!("Warning: could not open file at " + s) ; 0) | ~Some_vt(x) => begin let var viewstream: stream_vt(string) = $EXTRA.streamize_fileref_line(x) var n: int = stream_vt_length(viewstream) - 1 val _ = fileref_close(x) in n end end end
This will be mostly familiar to anyone with a Haskell background -
Nothing. But here we are matching on
a value with constructor
Some_vt rather than
Some, and for some reason prepending
~ to the
This is because
fileref_open_opt returns a value with a linear
Option_vt is just like
Option, except that it must always be consumed
in the scope that it is created. Linear types allow us to precisely pinpoint
where a value is needed, eliminating the need for garbage
collection (as in Rust). In this example, linear types force us to handle the error -
~ in the pattern match tells the compiler "immediately
free the memory after the right-hand side executes". Had we replaced the pattern
_, we would have seen a type error.
In practice, this means that we will be much more careful to avoid spurious
computation, e.g. filling
list_vt(a) with values we don't need.
Haskell has laziness to avoid spurious computation, but
it cannot benefit from unboxed data types at the same time. ATS is to my
only language that can offer both guarantees.