Pure Borrow: Linear Haskell Meets Rust-Style Borrowing
Abstract: A promising approach to unifying functional and imperative programming paradigms is to localize mutation using linear or affine types. Haskell, a purely functional language, was recently extended with linear types by Bernardy et al., named Linear Haskell. However, it remained unknown whether such a pure language could safely support non-local \emph{borrowing} in the style of Rust, where each borrower can be freely split and dropped without direct communication of ownership back to the lender. We answer this question affirmatively by \emph{Pure Borrow}, a novel framework that realizes Rust-style borrowing in Linear Haskell with purity. Notably, it features parallel state mutation with affine mutable references inside pure computation, unlike the IO and ST monads and existing Linear Haskell APIs. It also enjoys purity, lazy evaluation, first-class polymorphism and leak freedom, unlike Rust. We implement Pure Borrow simply as a library in Linear Haskell and demonstrate its power with a case study in parallel computing. We formalize the core of Pure Borrow and build a metatheory that works toward establishing safety, leak freedom and confluence, with a new, history-based model of borrowing.
Paper Prompts
Sign up for free to create and run prompts on this paper using GPT-5.
Top Community Prompts
Explain it Like I'm 14
What is this paper about?
This paper shows how to bring a powerful idea from the Rust programming language—borrowing—to pure Haskell without giving up Haskell’s strengths (like safety, predictability, and lazy evaluation). The authors introduce a library called Pure Borrow that lets Haskell code temporarily “borrow” access to data, change it efficiently, and even do those changes in parallel, all while staying mathematically clean (pure) and leak-free.
What questions does it try to answer?
- Can a purely functional language like Haskell safely support Rust-style borrowing, where borrowed pieces can be split, used, and dropped without constantly “handing the keys back”?
- Can we allow safe, parallel changes to data inside pure code?
- Can this be done as a simple library (no special compiler changes)?
- Can we reason formally that it’s safe, leak-free, and behaves consistently?
How does it work? (Explained simply)
To understand the challenge, imagine two worlds:
- Functional programming (Haskell): like doing math—same input, same output—easy to reason about.
- Imperative programming (Rust, C): like working with real tools—fast and efficient—but you have to be careful with shared tools (memory) to avoid mistakes.
The trick is to combine them: keep Haskell’s safety, but allow efficient updates when needed. Here are the main ideas, explained with everyday analogies:
- Linear/affine types: Imagine each resource (like a tool) comes with a “use-once” or “use at most once” ticket. This stops accidental copying or forgetting tools, which prevents many bugs and leaks.
- Borrowing (from Rust): Think of an object (like a toolbox) that you lend out:
- A mutable borrower: someone with the tool who can change things.
- A lender: the original owner, who will get it back later.
- A lifetime: a timer that says how long the loan lasts.
- Non-local return: borrowers can be split and dropped at different times; when the timer ends, the lender gets everything back automatically without each borrower handing it over directly.
- The BO monad (their main tool): Think of it as a “work area” marked with a wristband that says which lifetimes are currently active. Inside, you can:
- borrow objects (get borrowers and a lender),
- share borrowers for reading,
- split borrowers into independent parts,
- run two independent updates in parallel,
- and finally “reclaim” ownership safely when the lifetime is over.
- Lifetime tokens (Now and End): Like a green light (Now) meaning “this loan is active” and a red light (End) meaning “it’s over.” These tokens let the library enforce the rules without changing the compiler.
- Reborrowing: You can temporarily re-loan part of a current loan for a shorter time (like lending a wrench from a borrowed toolbox to someone else for a quick job), and then automatically get the original loan back.
- Parallelism safely: Because the system knows which parts are disjoint (no overlap), it can run updates to different pieces at the same time without risk of stepping on each other’s toes.
A quick picture in words: You split a vector (a fixed-size list) into two non-overlapping parts, update the first part in one thread and the second part in another thread, then join them back—no copying needed, no unsafe sharing, and the overall computation is still pure.
What did they build and find?
- A library for Haskell (no compiler changes needed) that brings Rust-style borrowing into pure Haskell code.
- A new “BO monad” that carries lifetime information and lets you:
- borrow and share data,
- split it into disjoint pieces,
- run parallel updates safely,
- reclaim the original data when the lifetime ends.
- They kept Haskell’s best features:
- Purity: results don’t depend on timing.
- Lazy evaluation and polymorphism (generic code still works).
- Leak freedom: resources are not accidentally lost.
- They showed a case study (like parallel quicksort) to demonstrate real performance benefits from safe parallel mutation in pure code.
- They also wrote down the math behind it (a formal core calculus) and a new “history-based” model for borrowing to argue for safety, leak freedom, and consistent behavior (confluence).
Why this matters:
- Previous Haskell tools had trade-offs:
- The ST monad allows local mutation but cannot safely do parallel updates.
- Linear Haskell before this required threading ownership very explicitly, which made some patterns clumsy.
- Rust is fast and safe for many things, but it’s not pure and can still leak in certain edge cases.
- Pure Borrow combines the good parts: Rust-like borrowing flexibility, with Haskell-like purity and leak freedom, plus safe parallel updates.
How did they approach it? (Steps in plain terms)
Here is the approach in a few steps:
- Represent lifetimes with explicit tokens (Now/End) and let code run only when the right tokens are present.
- Provide simple operations: borrow, share, split, reborrow, reclaim.
- Use a special “work area” (the BO monad) that carries lifetime info so the compiler and library can enforce the rules.
- Make parallel composition available only when parts are disjoint (so no data races).
- Prove the key properties in a simplified formal system so the design isn’t just a hack—it has solid foundations.
- Implement everything as a regular Haskell library that works with current GHC.
What could this lead to?
- Better high-performance Haskell libraries that stay pure but use efficient in-place updates under the hood.
- Safer and simpler parallel code: fewer race conditions and tricky bugs.
- A bridge between the functional world (clean, reliable reasoning) and the systems world (speed, control).
- Future tools that automate more of the “borrow checking” so programmers can write fast, safe parallel code with less effort.
In short, Pure Borrow shows that we can get Rust-like borrowing power inside pure Haskell, unlocking safe parallel speedups without giving up the guarantees that make functional programming so trustworthy.
Knowledge Gaps
Knowledge gaps, limitations, and open questions
The paper proposes Pure Borrow as a library-level framework for Rust-style borrowing in Linear Haskell and sketches a metatheory “working toward” safety, leak freedom, and confluence. The following points identify what remains missing, uncertain, or unexplored and could guide future research:
- Theory and soundness
- Provide a complete, mechanized soundness proof of the BO calculus that covers purity, leak freedom, and confluence under lazy evaluation and parallelism, rather than “working toward” these results.
- Extend the metatheory to model Haskell-specific features that impact soundness (e.g., laziness, strictness annotations, sharing, and thunk capture) to rule out lifetime use-after-end via delayed evaluation.
- Incorporate asynchronous exceptions and non-local control (e.g., exceptions, async exceptions, masked regions) into the semantics and proofs, showing that resource reclamation and leak freedom hold under failure.
- Prove determinism/confluence formally for programs that use parBO with arbitrary compositions of splitting, reborrowing, and sharing, including nested/recursive borrowing patterns.
- Clarify the semantic connection (and possible mismatch) between the history-based model used in the paper and the actual GHC execution/optimization model (e.g., rewriting rules, strictness/CPR analyses).
- Trust and unsafe implementation boundary
- Audit and formalize the “unsafe zero-cost coercions” used inside the library (e.g., to implement borrow/share/reclaim) and provide a small, clearly delimited trusted computing base with proofs that these coercions are sound under stated invariants.
- Address the risk that user-defined instances (e.g., Copyable, subtyping) could break safety if misdeclared; propose sealed classes, newtype wrappers, or compiler support to prevent unsound external instances.
- Align the metatheory with the actual library code (including all unsafe parts) via a refinement or translation proof that the Haskell implementation refines the formal model.
- Lifetimes and inference
- Move beyond manual lifetime token management (Nowα, Endα) to an algorithmic, type-directed lifetime inference and borrow checking (akin to Rust’s NLL), reducing annotation burden while preserving soundness.
- Provide a formal account of non-lexical lifetimes “to some extent”: characterize exactly which non-lexical patterns are supported, which are not, and why.
- Explore principled integration of lifetime intersection (α ∧ β) with type inference, subtyping, and polymorphism, including decidability and completeness of constraint solving.
- Clarify the role and restrictions of the Static lifetime (e.g., whether MutStatic or LendStatic can arise and how purity is preserved); formalize admissible constructions and exclusions.
- Expressivity limitations
- Integrate pattern matching with borrowing to support advanced Rust-like patterns (e.g., mixing move and borrow via ref patterns), or characterize why such patterns are fundamentally incompatible with Haskell’s semantics.
- Assess support for interior mutability analogues (e.g., Cell-/RefCell-like idioms) and whether Pure Borrow can model dynamic borrow checking or borrow-at-runtime patterns.
- Evaluate limits of generic splitting (split*) for complex/nested user-defined data types (GADTs, existential types, higher-rank fields), and specify which datatypes are splittable and how to derive splits safely.
- Clarify variance/subtyping boundaries: Mutα is invariant in the element type; document practical implications and provide patterns for working with covariant containers under mutation.
- Laziness and evaluation order
- Systematically analyze how laziness interacts with borrowing scopes and lifetime tokens, including:
- Preventing thunks from capturing Mut/Lend/Now references that may be forced after α ends.
- Required strictness (e.g., use of !) and where it must be enforced by the library vs. by user code.
- Provide guidelines or static checks that ensure no latent thunks outlive their borrowing lifetimes.
- Concurrency and parallelism
- Define the operational semantics of parBO precisely and show how linearity enforces disjointness under parallel evaluation; prove determinism and absence of data races despite lazy evaluation.
- Investigate failure semantics: what happens if one branch of parBO throws an exception or is killed by an async exception; ensure no lenders/borrowers are leaked and reclamation still happens.
- Evaluate scalability and scheduling behavior with GHC’s runtime (sparks, capabilities), and characterize when parBO offers performance benefits vs. overheads.
- Performance and evaluation
- Provide a comprehensive empirical evaluation beyond a single parallel quicksort case study:
- Microbenchmarks comparing Pure Borrow to ST, IO, and RIO for mutation-heavy kernels (arrays, graphs).
- Macrobenchmarks assessing scalability across cores and data sizes.
- Overheads of borrow/split/reborrow/share/copy operations and lifetime token management.
- Compare qualitatively and quantitatively with Rust implementations of similar algorithms to identify constant-factor gaps and opportunities for optimization.
- Tooling, ergonomics, and compiler support
- Assess type inference and error reporting in the presence of higher-rank polymorphism over lifetimes, intersection lifetimes, and subtyping; propose language or tooling support to improve the user experience.
- Explore compiler-level support for Linearly as a linear constraint (=o), reducing boilerplate and manual handling currently required in the GHC implementation.
- Investigate source-to-source transformations or syntactic sugar that hide Now/End management and strictness annotations while preserving soundness.
- Interoperability and ecosystem integration
- Study interactions with Haskell’s ST/IO/RIO, including embeddings and safe boundaries (e.g., running BO inside ST vs. mixing ST inside BO) and how to preserve purity guarantees.
- Analyze FFI implications: can borrowing safely span foreign calls, and can Pure Borrow interoperate with Rust code while maintaining Haskell’s purity and lifetime guarantees?
- Evaluate compatibility with common Haskell libraries (e.g., vector, bytestring, array libraries) and identify changes needed to expose borrow-friendly APIs without sacrificing safety.
- Memory management and GC
- Examine how lifetime tokens and borrowers interact with GHC’s garbage collector (e.g., retention of large structures due to lenders captured in closures, space leaks).
- Characterize memory behavior under long-lived shares (Ur (Shareα a)) and the conditions under which copying is preferable to sharing for space/time efficiency.
- API stability and generality
- Specify the boundaries of Copyable precisely and enforce them (e.g., forbid Copyable instances for types with hidden linear resources or mutable state).
- Evaluate whether the subtyping encoding (a <: b) remains decidable and predictable with larger instance sets, and whether additional compiler support is needed to avoid incoherence or exponential search.
These gaps outline concrete directions for strengthening the theoretical foundations, ensuring runtime robustness (especially with laziness, exceptions, and parallelism), improving usability through inference and tooling, broadening expressivity, and validating performance and interoperability in practice.
Practical Applications
Immediate Applications
The following are deployable now using the Pure Borrow library on GHC 9.10+ (with LinearTypes), offering Rust-style borrowing, parallel state mutation inside pure computations, and leak freedom.
- High-performance pure parallel algorithms in Haskell (Software/HPC)
- Use Pure Borrow’s BO monad, borrowing, and parBO to implement pure APIs with in-place mutation behind the scenes (e.g., parallel quicksort, partitioning, graph traversals, matrix/vector ops).
- Potential tools/products/workflows: A “pure-borrow” algorithms library; drop-in pure parallel replacements for common pure-but-slow routines in base/vector/array-like libraries.
- Assumptions/Dependencies: Requires refactoring to Linear Haskell idioms; GHC 9.10+ with LinearTypes; developers must design split/borrow operations that guarantee disjointness.
- Pure, leak-free mutable data structures with pure interfaces (Software)
- Implement vectors, queues, hash maps, and priority queues with internal affine mutable references and exposure as pure values, eliminating IO/ST in consumers while retaining performance.
- Potential tools/products/workflows: A data-structure suite built atop Pure Borrow; performance-critical components for compilers, parsers, and build tools.
- Assumptions/Dependencies: Requires careful API design for splitting and reborrowing; relies on the library’s zero-cost newtype wrappers and (internal) safe use of representational coercions.
- Safer parallelism primitives for Haskell applications (Software/Distributed Systems)
- Use parBO and linear types to enforce disjoint state in parallel computations, avoiding data races while keeping computations pure and deterministic.
- Potential tools/products/workflows: Concurrency combinators for safe parallel pipelines; task graphs that partition state via splitAt/splitPair before parallel execution.
- Assumptions/Dependencies: Depends on correct splitting/borrowing discipline; uses GHC’s runtime for parallelism; programmers must embrace linear usage patterns.
- Modernizing ST-based code without losing purity—and gaining parallelism (Software)
- Port ST monad–based mutable algorithms to Pure Borrow to enable safe parallel mutation and pure outward interfaces.
- Potential tools/products/workflows: Migration guides and linters; ST-to-BO refactoring templates for arrays/vectors and core algorithms.
- Assumptions/Dependencies: Requires adapting code to linear arrows and borrow/reborrow patterns; performance parity should be validated per workload.
- Deterministic, parallel, and auditable computations (Finance, Healthcare/MedTech)
- Leverage purity and parallel mutation to produce deterministic outputs independent of scheduling—critical for audited analytics, risk engines, actuarial calculations, and reproducible pipelines.
- Potential tools/products/workflows: Pure parallel analytics kernels (e.g., Monte Carlo core loops with partitioned state) used via pure APIs in risk/reporting systems.
- Assumptions/Dependencies: Domain code must be (or be wrapped as) pure Haskell; careful use of Copyable for non-persistent types to avoid unintended copying.
- Efficient pure wrappers for foreign code and buffers (Software/Systems)
- Wrap C/Rust mutable buffers with borrow/lend lifetimes while exposing pure Haskell interfaces, making memory ownership and reclamation explicit and leak-free.
- Potential tools/products/workflows: FFI shims that model lifetimes with End/Now tokens; safe pure APIs for codec buffers, parsers, and interop layers.
- Assumptions/Dependencies: Requires disciplined FFI boundary design to model lifetimes; careful mapping of Haskell lifetimes to foreign resources.
- Pedagogy and curriculum for linear/borrowing concepts (Education)
- Use Pure Borrow to teach linear types, affine borrowing, and deterministic parallelism with hands-on Haskell exercises.
- Potential tools/products/workflows: Course modules and lab assignments implementing parallel sort, partition, and in-place transforms in pure code.
- Assumptions/Dependencies: Students need exposure to LinearTypes; IDE/editor support is basic but sufficient.
- Performance boosts in Haskell-based blockchain and distributed systems (Finance/Blockchain)
- Apply pure-borrow patterns to node components (e.g., ledger evaluation, mempool manipulation, serialization buffers) to reduce allocation and improve throughput without sacrificing determinism.
- Potential tools/products/workflows: Pure parallel kernels within node software; internal mutable buffers safely reborrowed and reclaimed.
- Assumptions/Dependencies: Integration effort with existing codebases; maintain deterministic semantics across parallel paths.
- Low-allocation data processing and parsing (Software/Data)
- Build pure streaming/parsing libraries that internally mutate slice-like structures while exposing pure combinators (CSV/JSON parsing, ETL transforms).
- Potential tools/products/workflows: Pure parsing pipelines with measurable GC pressure reductions; split-based parallel parsing of chunks.
- Assumptions/Dependencies: Requires careful Copyable usage to avoid accidental deep copies; splitting strategies must align with data boundaries.
- Faster property-based testing and generators (Software/QA)
- Implement pure generators/shrinkers and test data builders using internal mutation for speed, maintaining pure interfaces for test determinism.
- Potential tools/products/workflows: Next-gen QuickCheck/Hedgehog add-ons using pure-borrow to scale to larger inputs.
- Assumptions/Dependencies: Generator internals must track lifetimes correctly; users remain unaware of internal mutation.
Long-Term Applications
These depend on further research, scaling, or toolchain/compiler development (e.g., automated lifetime inference, complete mechanized proofs).
- Compiler-level integration and automated borrow checking in GHC (Software/PL)
- Incorporate linear constraints and lifetime logic into the type checker with non-lexical lifetimes and inference, reducing manual Now/End token management.
- Potential tools/products/workflows: A GHC extension providing first-class borrowing with compiler-guided reborrowing/splitting; safer defaults across libraries.
- Assumptions/Dependencies: Substantial GHC changes; full safety/metatheory maturation; community adoption and migration support.
- Certified safety for safety-critical software (Software/Safety-critical, Healthcare, Aerospace)
- Mechanize safety, leak-freedom, and confluence proofs; produce a certified toolchain suitable for regulated environments.
- Potential tools/products/workflows: Proof-carrying libraries; audited computational kernels where deterministic parallelism is a requirement.
- Assumptions/Dependencies: Formalization in Coq/Agda/Isabelle; alignment with regulatory standards; performance validation.
- Unified Rust–Haskell borrowing across FFI (Software/Interoperability)
- Create tooling to map Rust lifetimes (&'a mut T) to Haskell’s Mutα/Lendα and back, enabling mixed-language systems with consistent ownership semantics.
- Potential tools/products/workflows: FFI generators that thread lifetimes and ensure reclaim; shared-safe buffer pools for cross-language pipelines.
- Assumptions/Dependencies: Stable interop conventions; runtime agreements on allocation and deallocation; error handling across language boundaries.
- Domain-specific languages with pure semantics and mutable runtimes (Robotics, Energy/Simulation)
- DSLs whose surface semantics are pure but runtime uses safe parallel mutation (e.g., physics engines, grid simulations, motion planning).
- Potential tools/products/workflows: Simulation engines and controllers built in Haskell with predictable determinism and high performance.
- Assumptions/Dependencies: Haskell suitability for real-time/latency-sensitive contexts; runtime scheduling guarantees.
- Hybrid persistent/ephemeral data structures with uniqueness-aware optimization (Software/Data Structures)
- Build libraries that opportunistically mutate in place when uniqueness (linear) holds and fall back to persistence otherwise, with automatic reborrowing.
- Potential tools/products/workflows: Next-gen “adaptive” containers for functional programs; compilers performing uniqueness-driven optimization.
- Assumptions/Dependencies: Advanced analysis/optimizations in compiler or libraries; careful benchmarking and heuristics.
- Numerical/tensor computing stack for Haskell (HPC/AI)
- Develop BLAS-like, tensor, and scientific computing libraries using Pure Borrow for memory management and parallel kernels, potentially bridging to GPU backends.
- Potential tools/products/workflows: Pure APIs for tensors with internal borrowed buffers; parallel ops partitioning tensors by split primitives.
- Assumptions/Dependencies: High-quality FFI to C/CUDA/Metal; lifetime-aware buffer pools; avoiding overheads from borrow orchestration.
- Region-aware runtime and GC optimizations (Software/Runtime)
- Exploit lifetime information to reduce GC pressure (e.g., region-based allocation and reclamation guided by Endα), improving throughput and latency.
- Potential tools/products/workflows: A GHC runtime mode that recognizes borrow lifetimes; memory diagnostics using lifetime graphs.
- Assumptions/Dependencies: Deep runtime changes; robust interaction with existing GC; proof of net benefits across workloads.
- Concurrency design patterns for servers/microservices (Industry/Software)
- Establish patterns for partitioned state and pure parallel updates in services where state shards are reborrowed to workers and reclaimed deterministically.
- Potential tools/products/workflows: Frameworks that codify borrow-based sharding and reclaim; safer scale-out designs.
- Assumptions/Dependencies: Integration with IO boundaries; clear lifecycle management for service state.
- Policy and best practices for deterministic, resource-safe functional programming (Policy/Education)
- Inform organizational standards for building deterministic analytics and simulations; promote training on linear/affine type safety.
- Potential tools/products/workflows: Internal guidelines, coding standards, and training tracks for teams adopting Pure Borrow patterns.
- Assumptions/Dependencies: Demonstrated ROI and reliability benefits; availability of educational materials and tooling.
- IDE and analysis tooling for lifetime/borrow visualization (Software DevEx)
- Provide editors and static analyzers that visualize borrow graphs, suggest reborrowing/splitting, and detect potential lifetime mismatches.
- Potential tools/products/workflows: HLS plugins, code actions to insert srunBO/reborrowing scaffolds; linters for lifetime subtyping.
- Assumptions/Dependencies: Stable API surface; program analyses for linear and borrow-aware code; community demand and contributions.
Glossary
- Affine mutable references: Mutable references that can be used at most once (droppable, not duplicable), enabling safe, localized mutation. Example: "parallel state mutation with affine mutable references inside pure computation"
- Affine types: Type discipline where values may be used at most once (they can be dropped but not copied), aiding safe resource management. Example: "Linear or affine types can localize the effect of state mutation"
- BO monad: A lifetime-parameterized monad for running borrowing computations inside pure code. Example: "The BO monad \hsinline{BOα} is a novel monad we introduce in Pure Borrow"
- Borrower: A reference that temporarily accesses an owned value without taking ownership; in this paper, can be mutable or shared and is affine. Example: "where each borrower can be freely split and dropped without direct communication of ownership back to the lender"
- Confluence: A property ensuring that different evaluation orders lead to the same result. Example: "build a metatheory that works toward establishing safety, leak freedom and confluence"
- Copyable: A type class marking values that can be duplicated from a shared borrower without moving ownership. Example: "We can copy the body \hsinline{a} out of a shared reference \hsinline{Shareα a} if \hsinline{Copyable a} holds."
- Consumable: A type class for values that can be safely discarded under linear use (but not duplicated). Example: "The type class \hsinline{Consumable a} abstracts data types that can be consumed (but not necessarily be shared) under linear binding."
- History-based model of borrowing: A semantic model that tracks the evolution of borrows over time to reason about safety. Example: "with a new, history-based model of borrowing."
- IO monad: Haskell’s monad for effectful, impure computations interacting with the external world. Example: "but its result can still be taken out into pure computation, unlike the IO monad"
- Iris: A higher-order concurrent separation logic framework used to verify program properties. Example: "in the separation logic Iris \cite{JungSSSTBD15-Iris}"
- Leak freedom: The guarantee that resources are not lost (i.e., no memory/resource leaks). Example: "It also enjoys purity, lazy evaluation, first-class polymorphism and leak freedom, unlike Rust."
- Lender: The entity retaining ultimate ownership while permitting borrowers; ownership is reclaimed after the lifetime ends. Example: "ownership back to the lender"
- Linear arrow: The function type constructor a -o b indicating its argument is used exactly once. Example: "Linear Haskell simply adds the linear arrow type \hsinline{a -o b}"
- Linear constraint: A constraint passed linearly (used exactly once), enabling APIs to depend on linear context evidence. Example: "It is introduced as a linear constraint \hsinline{Linearly =o}"
- Linearly: A special type class serving as a witness that code is running in a linear context. Example: "The type class \hsinline{Linearly} serves as a witness of linearity"
- Linear Haskell: An extension to Haskell that adds linear types to safely integrate mutation with purity. Example: "in the name of Linear Haskell."
- Linear logic: A substructural logic where propositions must be used exactly once, inspiring linear types. Example: "inspired by \citet{Girard87-linear-logic}'s linear logic."
- Linear types: Types enforcing exactly-once use of values, enabling safe in-place mutation and resource handling. Example: "Haskell, a purely functional language, was recently extended with linear types"
- Lifetime: A static scope during which borrows are valid; includes atomic, static, and intersection forms. Example: "A lifetime \hsinline{α :: Lifetime} is an atomic lifetime \hsinline{Al ι} for some id \hsinline{ι}, the static lifetime \hsinline{Static} that lives forever (\rsinline{'static} in Rust), or an intersection \hsinline{â§} of lifetimes."
- Lifetime intersection: The meet (greatest lower bound) of lifetimes, producing a shorter lifetime used for reborrowing. Example: "To obtain a shorter lifetime than \hsinline{α}, we use the intersection \hsinline{β ⧠α} of \hsinline{α} with a fresh lifetime \hsinline{β}."
- Lifetime logic: A logic for reasoning about lifetimes and borrowing, as used in RustBelt. Example: "RustBelt's lifetime logic"
- Lifetime tokens: Linear capabilities indicating whether a lifetime is live (Nowα) or ended (Endα). Example: "We introduce two basic tokens for lifetimes, the live lifetime token \hsinline{Nowα} and the dead lifetime token \hsinline{Endα}."
- Metatheory: The theoretical framework and proofs about the formal system’s properties. Example: "We formalize the core of Pure Borrow and build a metatheory that works toward establishing safety, leak freedom and confluence"
- Movable: A type class for values that can be moved into an unrestricted context (wrapped in Ur). Example: "The type class \hsinline{Movable a} abstracts data types that can be moved to an unrestricted context"
- Non-lexical lifetimes: Lifetimes whose validity is not restricted to lexical scopes, increasing flexibility. Example: "Notably, Pure Borrow supports non-lexical lifetimes \cite{Rust17-NLL} to some extent."
- Rank-2 polymorphism: Polymorphism allowing functions to accept arguments that are universally quantified themselves, used to encapsulate regions/lifetimes. Example: "Its key trick is to use rank-2 polymorphism over the region variable \hsinline{s} (technically working as a skolem)."
- Reborrowing: Creating a new (shorter) borrow from an existing mutable borrow, then restoring the original. Example: "Reborrowing solves this kind of situation."
- Region types: Type systems that associate memory with regions to control lifetimes and borrowing. Example: "originates from the long line of work on region types"
- RIO monad: A leak-free variant of IO in Linear Haskell that integrates linear resource tracking. Example: "It also introduced a leak-free variant of the IO monad, called the RIO monad."
- RustBelt: A semantic soundness proof of Rust’s type system that models borrowing using Iris. Example: "Some of Pure Borrow's design ideas originate from RustBelt's lifetime logic \cite{JungKD18-RustBelt}."
- Rust-style borrowing: The borrowing discipline from Rust where borrows can be split, dropped, and reclaimed non-locally. Example: "realizes Rust-style borrowing in Linear Haskell with purity."
- Separation logic: A program logic for reasoning about disjoint resources and mutable state. Example: "in the separation logic Iris \cite{JungSSSTBD15-Iris}"
- Skolem: A fresh, universally quantified placeholder used to prevent escaping references, here for regions. Example: "technically working as a skolem"
- ST monad: A Haskell monad enabling local mutable state that can be safely eliminated to pure results. Example: "The classical approach to achieve local mutation in Haskell is the \hsinline{ST} monad"
- Subtyping: A type relation allowing one type to be used where another is expected, formalized as a type class here. Example: "We introduce subtyping \hsinline{a <: b} as a type class"
- Unrestricted modality: The ! modality from linear logic allowing duplication and discarding of values. Example: "analogous to the -modality in linear logic."
- Ur: The “Unrestricted” wrapper type used to carry values in non-linear (duplicable) form inside linear code. Example: "We introduce a special data type \hsinline{Ur a} (
Ur' stands forUnrestricted')."
Collections
Sign up for free to add this paper to one or more collections.


