# Implementing Linear Haskell

Matthew Pickering & Arnaud Spiwack

## Linear Haskell: a Summary

Linearity on the arrow

a \rightarrow b\\ a \multimap b

type of linear functions

can be any type

$$f$$ linear
$$\iff$$

$$f u$$ consumed once $$\Rightarrow$$ $$u$$ consumed once

Linearity, not uniqueness

Backwards compatible

## Multiplicity polymorphism

a \rightarrow_\pi b

$$a \rightarrow b = a \rightarrow_\omega b$$

$$a \multimap b = a \rightarrow_1 b$$

$$a \rightarrow_p b$$: polymorphic

Instances

Properties

Semiring ( e.g. $$a*(b+c) = a*b + a*c$$)
Ordered ( e.g. $$a\leqslant c \Rightarrow a+b\leqslant c+b$$)

Joins ( i.e. $$a\vee b\leqslant c \iff a\leqslant c \wedge b\leqslant c$$)

$$\pi \leqslant \omega$$

## Typing rules

\cfrac { \Gamma \vdash f : \alpha \rightarrow_{\color{blue}\pi} \tau \quad \Delta \vdash u : \alpha } { \Gamma \mathbin{\color{darkorange}+} {\color{blue}\pi} \mathbin{\color{darkorange}*} \Delta \vdash f\,u : \tau }
\cfrac { \Gamma, x:_{\color{blue}\pi} \alpha \vdash u : \tau } { \Gamma \vdash \lambda x:_{\color{blue}\pi} \alpha. u : \alpha \rightarrow_{\color{blue}\pi} \tau }

## A type-checking algorithm

\cfrac { \Gamma \vdash f : \alpha \rightarrow_{\color{blue}\pi} \tau \leadsto U \quad \Gamma \vdash u : \alpha \leadsto V} { \Gamma \vdash f\,u : \tau \leadsto U \mathbin{\color{darkorange}+} {\color{blue}\pi} \mathbin{\color{darkorange}*} V}
\cfrac { \Gamma, x:\alpha \vdash u : \tau \leadsto (x\mapsto{\color{blue}\rho}, U) \quad {\color{blue}\rho} \mathrel{\color{darkorange}\leqslant}{\color{blue}\pi} } { \Gamma \vdash \lambda x:_{\color{blue}\pi} \alpha. u : \alpha \rightarrow_{\color{blue}\pi} \tau \leadsto U}

## Multiplicity data type

data Mult
= Zero
| One
| Omega
| Mult MultAdd Mult
| Mult MultMul Mult
| MultTy Type
data Weighted a
= Weighted Mult a
Weighted Type
Type

often

variables are mere type variables

data Multiplicity
= Omega
| One

Multiplicities as a type

## FunTy

(\rightarrow_\cdot)
FunTyCon :: Type
FunTy :: Mult -> Type -> Type -> Type
a \rightarrow_\pi b

Arguments:

RuntimeRep*2, Mult, Type*2

## Propagating to Core

data Var
= …
| Id {…
varType :: Type,
varMult :: Mult }

This is new

data Coercion
= …
| FunCo Role Coercion Coercion Coercion


New: multiplicity coercion

## Core transformations

\def\let{\mathop{\color{teal}\mathsf{let}}} \def\in{\mathbin{\color{darkmagenta}\mathsf{in~}}} \def\mult{\color{blue}} \let x_{\mult\pi} = \let y_{\mult\rho} = u \in v \in e\\ \Longrightarrow \phantom{a}\\ \let y_{\mult\pi*\rho} = u \in \let x_{\mult\pi} = v \in e
\def\let{\mathop{\color{teal}\mathsf{let}}} \def\in{\mathbin{\color{darkmagenta}\mathsf{in~}}} \def\mult{\color{blue}} \let x_{\phantom{\mult\pi}} = \let y_{\phantom{\mult\rho}} = u \in v \in e\\ \Longrightarrow \phantom{a}\\ \let y_{\phantom{\mult\pi*\rho}} = u \in \let x_{\phantom{\mult\pi}} = v \in e

## The Float Out incident

\def\let{\mathop{\color{teal}\mathsf{let}}} \def\in{\mathbin{\color{darkmagenta}\mathsf{in~}}} \def\case{\mathop{\color{teal}\mathsf{case}}} \def\of{\mathbin{\color{darkmagenta}\mathsf{of~}}} \def\mult{\color{blue}} \case u \of x_{\mult\pi}~\{ … ; pat \rightarrow \let y_{\mult\rho} = v \in e; … \} \\ \Longrightarrow \phantom{a}\\ \let y_{\mult??} = v \in \case u \of x_{\mult\pi}~\{ … ; pat \rightarrow e; … \}

(and inlining, and CSE,…)

\def\let{\mathop{\color{teal}\mathsf{let}}} \def\in{\mathbin{\color{darkmagenta}\mathsf{in~}}} \def\case{\mathop{\color{teal}\mathsf{case}}} \def\of{\mathbin{\color{darkmagenta}\mathsf{of~}}} \def\mult{\color{blue}} \case u \of x_{\phantom{\mult\pi}}~\{ … ; pat \rightarrow \let y_{\phantom{\mult\rho}} = v \in e; … \} \\ \Longrightarrow \phantom{a}\\ \let y_{\phantom{\mult??}} = v \in \case u \of x_{\phantom{\mult\pi}}~\{ … ; pat \rightarrow e; … \}

## Alias-like binders

\def\let{\mathop{\color{teal}\mathsf{let}}} \def\in{\mathbin{\color{darkmagenta}\mathsf{in~}}} \def\case{\mathop{\color{teal}\mathsf{case}}} \def\of{\mathbin{\color{darkmagenta}\mathsf{of~}}} \def\mult{\color{blue}} \dfrac { \Gamma \vdash u : \alpha \leadsto {\mult U} \quad \Gamma, x:_{\mult U} \alpha \vdash e: \tau \leadsto {\mult V} } { \Gamma \vdash \let x : \alpha = u \in e : \tau \leadsto {\mult V}}

## Pushing coercions

\def\let{\mathop{\color{teal}\mathsf{let}}} \def\in{\mathbin{\color{darkmagenta}\mathsf{in~}}} \def\case{\mathop{\color{teal}\mathsf{case}}} \def\of{\mathbin{\color{darkmagenta}\mathsf{of~}}} \def\mult{\color{blue}} (f \rhd co)\,u \Longrightarrow (f\,(u \rhd co_{arg})) \rhd co_{res}

What happened to $$co_{mult}$$‽ Bad! bad! bad!

Only push coercion when $$co_{mult} = \mathsf{refl}$$.

data Coercion
= …
| FunCo Role Coercion Coercion Coercion


## Wrapper for all

\mathsf{Just} : \forall a. a \multimap \mathsf{Maybe}\,a
\mathsf{Just} : \forall p\,a. a \rightarrow_p \mathsf{Maybe}\,a

This is key!

When used as a term.
Crucial for backwards compatibility

"inferred": doesn't affect visible type applications

Implemented as a wrapper

## Strictness analysis: CPR

$wf :: A -> (# C, D #) f :: A -> B f x = case$wf x of
(# y, z #) -> B y z

Linear: $$\verb|wf x|$$ is consumed exactly once.

But what if $$\mathsf{B} : a \multimap b \rightarrow B$$ ?

Then we need $$\verb|(#,#)| : a \multimap b \rightarrow \verb|(#|a,b\verb|#)|$$

Later! For now, deactivate CPR when not all fields linear

https://github.com/tweag/ghc/tree/linear-types

https://ghc.haskell.org/trac/ghc/wiki/LinearTypes/Implementation

https://github.com/ghc-proposals/ghc-proposals/pull/111

#### Implementing Linear Haskell

By Arnaud Spiwack

# Implementing Linear Haskell

As the linear type proposal is underway, and the specifics of how linear types should be exposed in Haskell are being debated, you may wonder: but how is it implemented? Is it easy? Is it hard? Is it small? Is it big? As a GHC developer what would it change for me in practice? This talk will describe our implementation in progress of the linear type feature. How we changed the linear arrow constructor, how type checking is performed, what changes are necessary in Core to account for linearity, etc…

• 695
Loading comments...