|
|
|
|
|
by phlip9
1611 days ago
|
|
I was a bit disappointed with linearity in QTT as I couldn't figured out how to create a safe API around a resizable array. The example given in the paper is a LinArray (https://github.com/idris-lang/Idris2/blob/main/libs/contrib/...). Unfortunately, as the community discovered, a user can "leak" a non-linear binding outside of the `newArray` constructor (which is what attempts to enforce linearity for all bindings). With multiple unrestricted handles, a user can accidentally double-free for instance. (https://github.com/idris-lang/Idris2/issues/613) The fundamental issue in this case is that linearity in QTT is a property of the parameter bindings and _not_ the type itself, meaning we can't easily express linearity as a _global_ property of the type. On the other hand, only affecting the parameter bindings makes it really easy to use runtime-erased/comptime stuff without reimplementing a bunch of common types as runtime- and comptime-only versions. ATS chooses the other path and makes linearity and runtime-erasure a part of the type (not without paying a hefty syntactic cost however). |
|
So I'm a bit confused why e.g. `read` is `(1 _ : arr t) -> Int -> Maybe t` and not `(1 _ : arr t) -> Int -> Res (Maybe t) (const (arr t))`.
But also isn't the `newArray` fixed by just rewrapping the output?
This is e.g. how Linear Haskell does it. The unrestricted multiplicity of the argument to `MkUnrestricted` prevents the bug here by only allowing you to output non-linear things (so it rejects wrapping the linear input in `MkUnrestricted`; you have to first convert it via a terminal operation into something else).The entire `Data.Linear.Array` seems to be in need of a once-over unless I'm misunderstanding something.
EDIT: Never mind, reading too quickly, I see the mread now that has the signature I'd imagine it should.