Quoting Kenton Varda (2018-08-27 20:41:57)
> Nice! Let me know when you want this added to the "other languages"
> page.
Go right ahead.
> How does zero-copy work out in Haskell? It seems like you can't really
> do zero-copy writes in a purely-functional way, right?
The low-level mechanisms in the library aren't ultimately that different
than in most implementations. It's possible to get locally-mutable state
in Haskell without breaking the global invariants via a trick with the
type system that basically emulates Rust's lifetimes -- so the mutable
variables can't be used outside of a certain scope. Naively this
involves a single copy on the way out for the data you want to keep, but
e.g. the vector library provides a create[1] function, which lets you
write code like (to paraphrase & reformat the example on that page):
immutableResult = create $ do
vec <- new 2
write vec 0 'a'
write vec 1 'b'
return vec
So you return a mutable value, which becomes unavailable when you leave
the scope, and you get an immutable one back.
Internally, create calls unsafeFreeze to cast from mutable -> immutable, but
provides an API that can't directly be used in ways that violate
referential transparency.
---
The harder questions were all around how to package stuff up in a way
that was actually comfortable to use; there are worse things than writing
Haskell like it's C, but I wanted to come up with something a little
higher level for common cases.
Right now there's a split high-level/low-level set of interfaces where the
high level ones basically ignore all of the novel properties of the wire
format, parse the thing up front, and expose an idiomatic Haskell data
type. This is not unlike the Go implementation's "pogs" package, except
that there's support in the code generator.
I have some ideas on other spots in the design space that get you a
larger share of the benefits of the wire format without much compromise
of programmer convenience, but they're not implemented yet. My main
interest is really in RPC, which is a much less weird fit for the
language anyway.
Ironically, *read* support was the harder direction to design for,
because of the need to track the traversal limit and deal with errors
in the midst of traversing the data. The current design again just
has a split, where you can either parse the whole thing up front
and forget about it, or write very imperative-looking code with
explicit error checks everywhere.
I have some ideas for how to provide most of the convenience of
the high-level API while still being able to do random access/only
access part of the message, and the API surface for them is pretty
tiny, so they should slot in nicely, but it hasn't happened yet.
[1]:
https://hackage.haskell.org/package/vector-0.12.0.1/docs/Data-Vector.html#v:create
--
You received this message because you are subscribed to the Google Groups
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.