Pure destination-passing style in Linear Haskell
tweag.io
tweag.io
The common name for this is "out parameters"
Out parameter is literally just a workaround for the lack of MRV, the callee still controls the allocation.
For instance `pthread_create` uses an out parameter:
pthread_t threadId;
int err = pthread_create(&threadId, NULL, &threadFunc, NULL);
the first parameter is uninitialised memory, it's only written to by the function. If C had tuples / MRV you'd say (int err, pthread_t threadId) = pthread_create(NULL, &threadFunc, NULL);
instead.But might still use a "destination passing" function, because the point of destination-passing is to make the caller control the allocation, and allow amortisation. "Destination passing" is pretty common in low-ish level Rust APIs for instance, while "out" parameters is largely forbidden (you'd need a function taking a reference to a MaybeUninit or such nonsense).
That's a good reason to rename one of them because they're completely different semantics and behaviour, and confusing one for the other is a direct route to segfault city.
char *buf = malloc(128);
snprintf(buf, 128, "hello");
the function is accepting a pointer to an uninitialized array of char, and initializing the array of char. With what you'd call an "out parameter", like char *buf;
asprintf(&buf, "hello");
the function is accepting a pointer to an uninitialized pointer to array of char, and initializing the pointer. The caller still controls the allocation of storage for the pointer itself.Caller provides one object for output:
void callee(Obj *obj);
Caller provides an array for output: void callee(Obj *obj, size_t obj_size);
Caller provides an pointer, to which callee allocates a new object: void callee(Obj **obj)[0] https://www.type-driven.org.uk/edwinb/linearity-and-erasure-...
I may well be missing something, but IIUC the linearity in Haskell is on the arrows - the function promises to use that argument exactly once (if it terminates - and never more than once).
I think this means `splitDArray` is broken. It consumes the linear argument, but then gives us two DArrays that we can forget to fill (or, probably not as bad, fill multiple times).
If that's the case, we probably want something more like
splitDArray :: Int -> DArray #-> (DArray #-> DArray #-> a) -> a
Please someone correct me if I've missed something :) alloc :: Int -> (DArray a ⊸ ()) ⊸ Array a
According to the linear Haskell paper: "f :: s ⊸ t guarantees that if (f u) is consumed exactly once, then the argument u is consumed exactly once." Also: "To consume a pair exactly once, pattern-match on it, and consume each component exactly once"So, if we call splitDArray inside that callback, then we are obliged to consume each of the resulting (DArray a, DArray a) exactly once to satisfy the constraint that the input is consumed exactly once.
Something passed into a function as a linear argument is considered to be "used" as many times as the result is consumed. So if we try to use either resulting `DArray` more than once (or forget to use one of them) we will have used the original `DArray` more than once (or forgotten to use it, ... or both). As you point out, that can't be done because we're inside the callback (although I'd followed that bit originally).
And that's why we have `Unrestricted` - for returning results we can reuse (or needn't use) while still consuming the arguments exactly once.
I'm very familiar with the Lisp family of languages (Scheme, Common Lisp, Clojure, Dylan, Julia...) and with some from the ML family as well (SML and Scala).
Is Haskell worth the effort for a small organization like a startup or a research lab? Would it bring something different when compared to those other languages? If so, in what domains? If one wants to have strict guarantees in the form of proofs why not using Agda or Idris instead?
Of all the languages I've used in production on the backend (Haskell, JVM, Go, Python), GHC's RTS is definitely the best.
Because they're research languages. The amount of non-toy software actually verified in them is zero. I'm not even sure if there's any non-toy software written in Idris besides the Idris compiler itself.
Coq's track record is better, but its language is ugly as hell in comparison (and to actually do anything you'd need to extract to Ocaml/Haskell anyway and the same applies to Agda).
* The type-system is a delightful and lets you control and secure your program in a unique way.
* The language model and idioms are elegant and highly expressive.
* Once you become proficient you can write code as fast as you would with python (without libraries/frameworks)
On top of this the library ecosystem, and development tools are about on par with general standards, and the compiler + runtime are exceptional.
> If a story has not had significant attention in the last year or so, a small number of reposts is ok. Otherwise we bury reposts as duplicates. (https://news.ycombinator.com/newsfaq.html)
1 upvote and 0 comments clearly isn't "significant attention", so why would it be?
Haskell's been around for a long time! GHC was begun in 1989.