
Encode state transitions in types using linear types - yorwba
http://www.tweag.io/posts/2017-08-03-linear-typestates.html
======
clord
I really like the name "Linear Types" better than RAII. C++ ctor/dtor pairs
are a sort of primitive linear type system that forces exactly one (implicit)
use for each instance created.

Linear types nicely generalizes this so that we don't need RAII wrappers or
whatever. Just produce values and pass them around, eventually to be consumed.
It _feels_ like this is a powerful language idea.

~~~
moosingin3space
Rust uses a similar (but significantly weaker) system called "affine types"
underlying its borrow checker.

~~~
kibwen
Nit: Rust's affine type system is orthogonal to its borrow checker, rather
than underlying it (though they're both crucial to Rust's system of memory
safety, of course).

~~~
moosingin3space
Would it be correct to say that the affine type system underlies the ownership
paradigm?

~~~
kibwen
Absolutely, I was just trying to avoid using "ownership" in my previous
comment because it's more of an abstract concept than the type system and the
borrow checker (which have concrete phases in the compiler, typeck and
borrowck (though typeck also does more than just enforce linearity (er,
affininity?))).

------
theboywho
I don't know Haskell but this looks like Phantom Types in Scala.

Can anyone who knows both languages enlighten us ?

More on Scala Phantom types here [https://gigiigig.github.io/tlp-step-by-
step/phantom-types.ht...](https://gigiigig.github.io/tlp-step-by-step/phantom-
types.html)

~~~
yorwba
I don't know Scala, but Phantom Types look like they only encode the state at
the type level, but don't prevent you from copying e.g. the closed door before
opening it, which would be undesirable if the state transition corresponds to
a side effect.

Linear types can guarantee that the object participating in a state transition
is not reused, which prevents accidentally referring to invalidated data.

~~~
mcguire
This, exactly.

You can use phantom types to mark the difference between bound and unbound
sockets, but you need the linear type system to prevent the unbound value from
being used again.

------
itamarst
The short version, as I understand it, is this will enable the GHC Haskell
compiler to validate state machines at compile time. Which is pretty awesome.

~~~
agumonkey
A tiny bit of model checking never hurt I guess.

------
yorwba
Discussion of the previous post in the series:
[https://news.ycombinator.com/item?id=13866787](https://news.ycombinator.com/item?id=13866787)

------
kibwen
A linear type system isn't strictly necessary for this pattern; this is a
common trick in Rust, which only has affine types:
[http://insanitybit.github.io/2016/05/30/beyond-memory-
safety...](http://insanitybit.github.io/2016/05/30/beyond-memory-safety-with-
types) . Indeed, it's lovely for validating state machines at compile time.

~~~
runeks
Rust can’t guarantee that a value is consumed exactly once.

This example creates a monad parametized over how many times a return value
must be consumed. It has two settings: 1 (exactly once), and ω, which I’m
prettying sure is the Greek abbreviation of “whatever” (zero or more times).

~~~
octachron
> ω, which I’m prettying sure is the Greek abbreviation of “whatever” (zero or
> more times).

Or it is the classical notation for the ordinal associated with the set of
integers ℕ, aka any number of times.

~~~
runeks
I guess that’s also possible. I prefer my own explanation though, but then
again I’m no mathematician.

