Skip to content

A more fine-grained version of state threads (`ST`)

License

Notifications You must be signed in to change notification settings

david-davies/reference-threads

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Reference Threads (RT)

A more fine-grained version of state threads (ST). Instead of carrying around a type parameter to represent the lifetime of the overall stateful computation, RT instead parameterises its references with a unique lifetime. This allows them to have more fine-grained lifetimes and avoids the need for the overall computation to carry a type parameter: this makes them more suitable for frictionless and safe use in other libraries without exposing anything to the user unnecessarily.

As an example, gigaparsec makes use of RT internally to facilitate the use of references in a parser. If the user is not using stateful references, they can completely ignore the functionality without any additional s parameter on their parsers.

Compared with ST, the downside of using RT's Ref is that the newRef operation is necessarily written in continuation-passing style, with the created reference only live during the continuation. As an example, consider the differences between the following operation types:

Operation ST RT
Monad running (forall s. ST s a) -> a RT a -> a
Reference creation a -> ST s (STRef s a) a -> (forall r. Ref r a -> RT b) -> RT b

The introducer the rank-2 type is the key difference between these abstractions. This is a small ergonomic price to pay for the luxury of not needing the type-parameter on the rest of the computation.

Unsoundness

The RT monad is a hybrid between the safe ST and the more unsafe IO monad. While RT cannot perform IO, it is still possible for a Ref to leak out from underneath its enclosing scope by packing it into an existential.

data EscapedRef a = forall r. EscapedRef (Ref r a)
escape :: a -> RT (EscapedRef a)
escape x = newRef x (return . EscapedRef)

This effectively decays it into the equivalent of an IORef when unpacked. However, it is not possible to use coerce to allow a reference to escape its scope.

About

A more fine-grained version of state threads (`ST`)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Haskell 100.0%