Programming in Vinyl Jon Sterling jonmsterling.com May 18, 2014
Jun 23, 2015
Programming in Vinyl
Jon Sterlingjonmsterling.com
May 18, 2014
Records in GHC 7.8
I Haskell records are nominally typedI They may not share field names
data R = R { x :: X }data R’ = R’ { x :: X } −− ˆ Error
Records in GHC 7.8
I Haskell records are nominally typed
I They may not share field names
data R = R { x :: X }data R’ = R’ { x :: X } −− ˆ Error
Records in GHC 7.8
I Haskell records are nominally typedI They may not share field names
data R = R { x :: X }data R’ = R’ { x :: X } −− ˆ Error
Records in GHC 7.8
I Haskell records are nominally typedI They may not share field names
data R = R { x :: X }
data R’ = R’ { x :: X } −− ˆ Error
Records in GHC 7.8
I Haskell records are nominally typedI They may not share field names
data R = R { x :: X }data R’ = R’ { x :: X } −− ˆ Error
Structural Typing
I Sharing field names and accessorsI Record types may be characterized structurally
Structural Typing
I Sharing field names and accessors
I Record types may be characterized structurally
Structural Typing
I Sharing field names and accessorsI Record types may be characterized structurally
Row Polymorphism
How do we express the type of a function which adds afield to a record?
Row Polymorphism
How do we express the type of a function which adds afield to a record?
Row Polymorphism
How do we express the type of a function which adds afield to a record?
x : {foo : A}f(x) : {foo : A, bar : B}
Row Polymorphism
How do we express the type of a function which adds afield to a record?
x : {foo : A; ~rs}f(x) : {foo : A, bar : B; ~rs}
Roll Your Own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗]→ ∗ whereRNil :: Rec ’[](:&) :: !t→ !(Rec rs)→ Rec ((s ::: t) ’: rs)
class s ∈ (rs :: [∗])class ss ⊆ (rs :: [∗]) where
cast :: Rec rs→ Rec ss(=:) : s ::: t→ t→ Rec ’[s ::: t](⊕) : Rec ss→ Rec ts→ Rec (ss ++ ts)lens : s ::: t ∈ rs⇒ s ::: t→ Lens’ (Rec rs) t
Roll Your Own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗]→ ∗ whereRNil :: Rec ’[](:&) :: !t→ !(Rec rs)→ Rec ((s ::: t) ’: rs)
class s ∈ (rs :: [∗])class ss ⊆ (rs :: [∗]) where
cast :: Rec rs→ Rec ss(=:) : s ::: t→ t→ Rec ’[s ::: t](⊕) : Rec ss→ Rec ts→ Rec (ss ++ ts)lens : s ::: t ∈ rs⇒ s ::: t→ Lens’ (Rec rs) t
Roll Your Own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗]→ ∗ where
RNil :: Rec ’[](:&) :: !t→ !(Rec rs)→ Rec ((s ::: t) ’: rs)
class s ∈ (rs :: [∗])class ss ⊆ (rs :: [∗]) where
cast :: Rec rs→ Rec ss(=:) : s ::: t→ t→ Rec ’[s ::: t](⊕) : Rec ss→ Rec ts→ Rec (ss ++ ts)lens : s ::: t ∈ rs⇒ s ::: t→ Lens’ (Rec rs) t
Roll Your Own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗]→ ∗ whereRNil :: Rec ’[]
(:&) :: !t→ !(Rec rs)→ Rec ((s ::: t) ’: rs)
class s ∈ (rs :: [∗])class ss ⊆ (rs :: [∗]) where
cast :: Rec rs→ Rec ss(=:) : s ::: t→ t→ Rec ’[s ::: t](⊕) : Rec ss→ Rec ts→ Rec (ss ++ ts)lens : s ::: t ∈ rs⇒ s ::: t→ Lens’ (Rec rs) t
Roll Your Own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗]→ ∗ whereRNil :: Rec ’[](:&) :: !t→ !(Rec rs)→ Rec ((s ::: t) ’: rs)
class s ∈ (rs :: [∗])class ss ⊆ (rs :: [∗]) where
cast :: Rec rs→ Rec ss(=:) : s ::: t→ t→ Rec ’[s ::: t](⊕) : Rec ss→ Rec ts→ Rec (ss ++ ts)lens : s ::: t ∈ rs⇒ s ::: t→ Lens’ (Rec rs) t
Roll Your Own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗]→ ∗ whereRNil :: Rec ’[](:&) :: !t→ !(Rec rs)→ Rec ((s ::: t) ’: rs)
class s ∈ (rs :: [∗])
class ss ⊆ (rs :: [∗]) wherecast :: Rec rs→ Rec ss
(=:) : s ::: t→ t→ Rec ’[s ::: t](⊕) : Rec ss→ Rec ts→ Rec (ss ++ ts)lens : s ::: t ∈ rs⇒ s ::: t→ Lens’ (Rec rs) t
Roll Your Own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗]→ ∗ whereRNil :: Rec ’[](:&) :: !t→ !(Rec rs)→ Rec ((s ::: t) ’: rs)
class s ∈ (rs :: [∗])class ss ⊆ (rs :: [∗]) where
cast :: Rec rs→ Rec ss
(=:) : s ::: t→ t→ Rec ’[s ::: t](⊕) : Rec ss→ Rec ts→ Rec (ss ++ ts)lens : s ::: t ∈ rs⇒ s ::: t→ Lens’ (Rec rs) t
Roll Your Own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗]→ ∗ whereRNil :: Rec ’[](:&) :: !t→ !(Rec rs)→ Rec ((s ::: t) ’: rs)
class s ∈ (rs :: [∗])class ss ⊆ (rs :: [∗]) where
cast :: Rec rs→ Rec ss(=:) : s ::: t→ t→ Rec ’[s ::: t]
(⊕) : Rec ss→ Rec ts→ Rec (ss ++ ts)lens : s ::: t ∈ rs⇒ s ::: t→ Lens’ (Rec rs) t
Roll Your Own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗]→ ∗ whereRNil :: Rec ’[](:&) :: !t→ !(Rec rs)→ Rec ((s ::: t) ’: rs)
class s ∈ (rs :: [∗])class ss ⊆ (rs :: [∗]) where
cast :: Rec rs→ Rec ss(=:) : s ::: t→ t→ Rec ’[s ::: t](⊕) : Rec ss→ Rec ts→ Rec (ss ++ ts)
lens : s ::: t ∈ rs⇒ s ::: t→ Lens’ (Rec rs) t
Roll Your Own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗]→ ∗ whereRNil :: Rec ’[](:&) :: !t→ !(Rec rs)→ Rec ((s ::: t) ’: rs)
class s ∈ (rs :: [∗])class ss ⊆ (rs :: [∗]) where
cast :: Rec rs→ Rec ss(=:) : s ::: t→ t→ Rec ’[s ::: t](⊕) : Rec ss→ Rec ts→ Rec (ss ++ ts)lens : s ::: t ∈ rs⇒ s ::: t→ Lens’ (Rec rs) t
Roll Your Own in Haskell
f :: Rec (”foo” ::: A ’: rs)→ Rec (”bar” ::: B ’: ”foo” ::: A ’: rs)
Roll Your Own in Haskell
f :: Rec (”foo” ::: A ’: rs)→ Rec (”bar” ::: B ’: ”foo” ::: A ’: rs)
Universes a la Tarski
I A type U of codes for types.I Function ElU : U → Type.
Γ ` s : UΓ ` ElU(s) : Type
Universes a la Tarski
I A type U of codes for types.
I Function ElU : U → Type.
Γ ` s : UΓ ` ElU(s) : Type
Universes a la Tarski
I A type U of codes for types.I Function ElU : U → Type.
Γ ` s : UΓ ` ElU(s) : Type
Universes a la Tarski
I A type U of codes for types.I Function ElU : U → Type.
Γ ` s : UΓ ` ElU(s) : Type
Universes a la Tarski
Type
Universes a la Tarski
Type
Universes a la Tarski
Type
Universes a la Tarski
Type
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:
I Statics:
A : Type Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type
Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type
Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type Home,Office : Label
Name : A
` : LabelPhone[`],Email[`] : A
s : AElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : A
s : AElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string
ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
A Closed Universe
Let A be a universe of address books:I Statics:
A : Type Label : Type Home,Office : Label
Name : A` : Label
Phone[`],Email[`] : As : A
ElA(s) : Type
I Dynamics:
ElA(Name) string ElA(Email[`]) string
ElA(Phone[`]) list(N)
Records as Products
Records as Products
Records: the product of the image of ElU in Typerestricted to a subset of U .
Records as Products
Records: the product of the image of ElU in Typerestricted to a subset of U .
recordU ∑V⊆U
∏V
ElU |V
Records as Products
Type
Records as Products
Type
×× ×
×
Records as Products
recordU ∑V⊆U
∏V
ElU |V
Example Record
recordU ∑V⊆U
∏V
ElU |V
A′ {Name,Email Work}ex : recordU
ex 〈A′, λ.{Name 7→ ”Robert Harper”;Email Work 7→ ”[email protected]”}〉
Example Record
recordU ∑V⊆U
∏V
ElU |V
A′ {Name,Email Work}
ex : recordU
ex 〈A′, λ.{Name 7→ ”Robert Harper”;Email Work 7→ ”[email protected]”}〉
Example Record
recordU ∑V⊆U
∏V
ElU |V
A′ {Name,Email Work}ex : recordU
ex 〈A′, λ.{Name 7→ ”Robert Harper”;Email Work 7→ ”[email protected]”}〉
Example Record
recordU ∑V⊆U
∏V
ElU |V
A′ {Name,Email Work}ex : recordU
ex 〈A′, λ.{Name 7→ ”Robert Harper”;Email Work 7→ ”[email protected]”}〉
Presheaves
A presheaf on some space X is a functorO(X)op → Type, where O is the category of open sets ofX for whatever topology you have chosen.
Presheaves
A presheaf on some space X is a functorO(X)op → Type, where O is the category of open sets ofX for whatever topology you have chosen.
Topologies on some space X
I What are the open sets on X?I The empty set and X are open setsI The union of open sets is openI Finite intersections of open sets are open
Topologies on some space X
I What are the open sets on X?
I The empty set and X are open setsI The union of open sets is openI Finite intersections of open sets are open
Topologies on some space X
I What are the open sets on X?I The empty set and X are open setsI The union of open sets is openI Finite intersections of open sets are open
Records are Presheaves
I Let O = P, the discrete topologyI Then records on a universe X give rise to a presheafR: subset inclusions are taken to casts from larger tosmaller records
for V ⊆ X R(V ) :≡∏V
ElX |V : Type
for i : V ↪→ U R(i) :≡ cast : R(U)→ R(V )
Records are Presheaves
I Let O = P, the discrete topology
I Then records on a universe X give rise to a presheafR: subset inclusions are taken to casts from larger tosmaller records
for V ⊆ X R(V ) :≡∏V
ElX |V : Type
for i : V ↪→ U R(i) :≡ cast : R(U)→ R(V )
Records are Presheaves
I Let O = P, the discrete topologyI Then records on a universe X give rise to a presheafR: subset inclusions are taken to casts from larger tosmaller records
for V ⊆ X R(V ) :≡∏V
ElX |V : Type
for i : V ↪→ U R(i) :≡ cast : R(U)→ R(V )
Records are Presheaves
I Let O = P, the discrete topologyI Then records on a universe X give rise to a presheafR: subset inclusions are taken to casts from larger tosmaller records
for V ⊆ X R(V ) :≡∏V
ElX |V : Type
for i : V ↪→ U R(i) :≡ cast : R(U)→ R(V )
Records are Presheaves
I Let O = P, the discrete topologyI Then records on a universe X give rise to a presheafR: subset inclusions are taken to casts from larger tosmaller records
for V ⊆ X R(V ) :≡∏V
ElX |V : Type
for i : V ↪→ U R(i) :≡ cast : R(U)→ R(V )
Records are Sheaves
For a cover U =⋃
i Ui on X, then:
e = λr.λi. castUi(r)
p = λf.λi.λj. castUi∩Uj(f(i))
q = λf.λi.λj. castUi∩Uj(f(j))
Records are Sheaves
For a cover U =⋃
i Ui on X, then:
R(U)∏
iR(Ui)∏
i,jR(Ui ∩ Uj)e p
q
is an equalizer, where
e = λr.λi. castUi(r)
p = λf.λi.λj. castUi∩Uj(f(i))
q = λf.λi.λj. castUi∩Uj(f(j))
Records are SheavesFor a cover U =
⋃i Ui on X, then:
R(U)∏
iR(Ui)∏
i,jR(Ui ∩ Uj)
Γ
e
m!u
p
q
where
e = λr.λi. castUi(r)
p = λf.λi.λj. castUi∩Uj(f(i))
q = λf.λi.λj. castUi∩Uj(f(j))
Corecords as Sums
Corecords as Sums
Corecords (extensible variants): the sum of the image ofElU in Type restricted to a subset of U .
Corecords as Sums
Corecords (extensible variants): the sum of the image ofElU in Type restricted to a subset of U .
corecordU ∑V⊆U
∑V
ElU |V
Corecords as Sums
Type
Corecords as Sums
Type
++ +
+
Corecords as Sums
corecordU ∑V⊆U
∑V
ElU |V
Doing it in Haskell
I Create a universe U at the type-levelI Use type families to approximate ElUI Parameterize Rec by U , ElU?
Doing it in Haskell
I Create a universe U at the type-level
I Use type families to approximate ElUI Parameterize Rec by U , ElU?
Doing it in Haskell
I Create a universe U at the type-levelI Use type families to approximate ElU
I Parameterize Rec by U , ElU?
Doing it in Haskell
I Create a universe U at the type-levelI Use type families to approximate ElUI Parameterize Rec by U , ElU?
Records in Haskell
data Rec :: (U → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU ’[](:&) :: !(elU r)→ !(Rec elU rs)→ Rec elU (r ’: rs)
Records in Haskell
data Rec :: (U → ∗)→ [ U ]→ ∗ where
RNil :: Rec elU ’[](:&) :: !(elU r)→ !(Rec elU rs)→ Rec elU (r ’: rs)
Records in Haskell
data Rec :: (U → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU ’[]
(:&) :: !(elU r)→ !(Rec elU rs)→ Rec elU (r ’: rs)
Records in Haskell
data Rec :: (U → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU ’[](:&) :: !(elU r)→ !(Rec elU rs)→ Rec elU (r ’: rs)
Records in Haskell (Actually)
data TyFun :: ∗ → ∗ → ∗type family (f :: TyFun k l→ ∗) $ (x :: k) :: l
data Rec :: (TyFun U ∗ → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU ’[](:&) :: !(elU $ r)→ !(Rec elU rs)→ Rec elU (r ’: rs)
Records in Haskell (Actually)
data TyFun :: ∗ → ∗ → ∗
type family (f :: TyFun k l→ ∗) $ (x :: k) :: l
data Rec :: (TyFun U ∗ → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU ’[](:&) :: !(elU $ r)→ !(Rec elU rs)→ Rec elU (r ’: rs)
Records in Haskell (Actually)
data TyFun :: ∗ → ∗ → ∗type family (f :: TyFun k l→ ∗) $ (x :: k) :: l
data Rec :: (TyFun U ∗ → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU ’[](:&) :: !(elU $ r)→ !(Rec elU rs)→ Rec elU (r ’: rs)
Records in Haskell (Actually)
data TyFun :: ∗ → ∗ → ∗type family (f :: TyFun k l→ ∗) $ (x :: k) :: l
data Rec :: (TyFun U ∗ → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU ’[](:&) :: !(elU $ r)→ !(Rec elU rs)→ Rec elU (r ’: rs)
Recovering HList
data Id :: (TyFun k k)→ ∗ wheretype instance Id $ x = x
type HList rs = Rec Id rs
ex :: HList [Z, Bool, String]ex = 34 :& True :& ”vinyl” :& RNil
Recovering HList
data Id :: (TyFun k k)→ ∗ wheretype instance Id $ x = x
type HList rs = Rec Id rs
ex :: HList [Z, Bool, String]ex = 34 :& True :& ”vinyl” :& RNil
Recovering HList
data Id :: (TyFun k k)→ ∗ wheretype instance Id $ x = x
type HList rs = Rec Id rs
ex :: HList [Z, Bool, String]ex = 34 :& True :& ”vinyl” :& RNil
Recovering HList
data Id :: (TyFun k k)→ ∗ wheretype instance Id $ x = x
type HList rs = Rec Id rs
ex :: HList [Z, Bool, String]
ex = 34 :& True :& ”vinyl” :& RNil
Recovering HList
data Id :: (TyFun k k)→ ∗ wheretype instance Id $ x = x
type HList rs = Rec Id rs
ex :: HList [Z, Bool, String]ex = 34 :& True :& ”vinyl” :& RNil
Validating Records
bob :: Rec ElA [Name, Email Work]
bob = Name =: ”Robert Harper”⊕ Email Work =: ”[email protected]”
validateName :: String→ Either Error StringvalidateEmail :: String→ Either Error StringvalidatePhone :: [N]→ Either Error [N]
*unnnnnhhh...*
validateContact:: Rec ElA [Name, Email Work]→ Either Error (Rec ElA [Name, Email Work])
Validating Records
bob :: Rec ElA [Name, Email Work]bob = Name =: ”Robert Harper”⊕ Email Work =: ”[email protected]”
validateName :: String→ Either Error StringvalidateEmail :: String→ Either Error StringvalidatePhone :: [N]→ Either Error [N]
*unnnnnhhh...*
validateContact:: Rec ElA [Name, Email Work]→ Either Error (Rec ElA [Name, Email Work])
Validating Records
bob :: Rec ElA [Name, Email Work]bob = Name =: ”Robert Harper”⊕ Email Work =: ”[email protected]”
validateName :: String→ Either Error StringvalidateEmail :: String→ Either Error StringvalidatePhone :: [N]→ Either Error [N]
*unnnnnhhh...*
validateContact:: Rec ElA [Name, Email Work]→ Either Error (Rec ElA [Name, Email Work])
Validating Records
bob :: Rec ElA [Name, Email Work]bob = Name =: ”Robert Harper”⊕ Email Work =: ”[email protected]”
validateName :: String→ Either Error StringvalidateEmail :: String→ Either Error StringvalidatePhone :: [N]→ Either Error [N]
*unnnnnhhh...*
validateContact:: Rec ElA [Name, Email Work]→ Either Error (Rec ElA [Name, Email Work])
Validating Records
bob :: Rec ElA [Name, Email Work]bob = Name =: ”Robert Harper”⊕ Email Work =: ”[email protected]”
validateName :: String→ Either Error StringvalidateEmail :: String→ Either Error StringvalidatePhone :: [N]→ Either Error [N]
*unnnnnhhh...*
validateContact:: Rec ElA [Name, Email Work]→ Either Error (Rec ElA [Name, Email Work])
Welp.
Effects inside records
data Rec :: (TyFun U ∗ → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU ’[](:&) :: !(elU $ r)→ !(Rec elU rs)→ Rec elU (r ’: rs)
Effects inside records
data Rec :: (TyFun U ∗ → ∗)→ (∗ → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU f ’[](:&) :: !(f (elU $ r))→ !(Rec elU f rs)→ Rec elU f (r ’: rs)
(=:) : Applicative f⇒ sing r→ elU $ r→ Rec elU f ’[r]k =: x = pure x :& RNil
(⇐\): sing r→ f (elU $ r)→ Rec elU f ’[r]k⇐\ x = x :& RNil
Effects inside records
data Rec :: (TyFun U ∗ → ∗)→ (∗ → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU f ’[](:&) :: !(f (elU $ r))→ !(Rec elU f rs)→ Rec elU f (r ’: rs)
(=:) : Applicative f⇒ sing r→ elU $ r→ Rec elU f ’[r]
k =: x = pure x :& RNil
(⇐\): sing r→ f (elU $ r)→ Rec elU f ’[r]k⇐\ x = x :& RNil
Effects inside records
data Rec :: (TyFun U ∗ → ∗)→ (∗ → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU f ’[](:&) :: !(f (elU $ r))→ !(Rec elU f rs)→ Rec elU f (r ’: rs)
(=:) : Applicative f⇒ sing r→ elU $ r→ Rec elU f ’[r]k =: x = pure x :& RNil
(⇐\): sing r→ f (elU $ r)→ Rec elU f ’[r]k⇐\ x = x :& RNil
Effects inside records
data Rec :: (TyFun U ∗ → ∗)→ (∗ → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU f ’[](:&) :: !(f (elU $ r))→ !(Rec elU f rs)→ Rec elU f (r ’: rs)
(=:) : Applicative f⇒ sing r→ elU $ r→ Rec elU f ’[r]k =: x = pure x :& RNil
(⇐\): sing r→ f (elU $ r)→ Rec elU f ’[r]
k⇐\ x = x :& RNil
Effects inside records
data Rec :: (TyFun U ∗ → ∗)→ (∗ → ∗)→ [ U ]→ ∗ whereRNil :: Rec elU f ’[](:&) :: !(f (elU $ r))→ !(Rec elU f rs)→ Rec elU f (r ’: rs)
(=:) : Applicative f⇒ sing r→ elU $ r→ Rec elU f ’[r]k =: x = pure x :& RNil
(⇐\): sing r→ f (elU $ r)→ Rec elU f ’[r]k⇐\ x = x :& RNil
Compositional Validation
type RecA = Rec ElA
bob :: RecA Identity [Name, Email Work]bob = Name =: ”Robert Harper”⊕ Email Work =: ”[email protected]”
Compositional Validation
type RecA = Rec ElAbob :: RecA Identity [Name, Email Work]
bob = Name =: ”Robert Harper”⊕ Email Work =: ”[email protected]”
Compositional Validation
type RecA = Rec ElAbob :: RecA Identity [Name, Email Work]bob = Name =: ”Robert Harper”⊕ Email Work =: ”[email protected]”
Compositional Validation
type RecA = Rec ElAbob :: RecA Identity [Name, Email Work]bob = Name =: ”Robert Harper”⊕ Email Work =: ”[email protected]”
Compositional Validation
type Validator a = a→ Either Error a
validateName :: RecA Validator ’[Name]validatePhone :: ∀`. RecA Validator ’[Phone `]validateEmail :: ∀`. RecA Validator ’[Email `]
type TotalContact =[ Name, Email Home, Email Work, Phone Home, Phone Work ]
validateContact :: RecA Validator TotalContactvalidateContact = validateName
⊕ validateEmail⊕ validateEmail⊕ validatePhone⊕ validatePhone
Compositional Validation
type Validator a = a→ Either Error avalidateName :: RecA Validator ’[Name]validatePhone :: ∀`. RecA Validator ’[Phone `]validateEmail :: ∀`. RecA Validator ’[Email `]
type TotalContact =[ Name, Email Home, Email Work, Phone Home, Phone Work ]
validateContact :: RecA Validator TotalContactvalidateContact = validateName
⊕ validateEmail⊕ validateEmail⊕ validatePhone⊕ validatePhone
Compositional Validation
type Validator a = a→ Either Error avalidateName :: RecA Validator ’[Name]validatePhone :: ∀`. RecA Validator ’[Phone `]validateEmail :: ∀`. RecA Validator ’[Email `]
type TotalContact =[ Name, Email Home, Email Work, Phone Home, Phone Work ]
validateContact :: RecA Validator TotalContactvalidateContact = validateName
⊕ validateEmail⊕ validateEmail⊕ validatePhone⊕ validatePhone
Compositional Validation
type Validator a = a→ Either Error avalidateName :: RecA Validator ’[Name]validatePhone :: ∀`. RecA Validator ’[Phone `]validateEmail :: ∀`. RecA Validator ’[Email `]
type TotalContact =[ Name, Email Home, Email Work, Phone Home, Phone Work ]
validateContact :: RecA Validator TotalContactvalidateContact = validateName
⊕ validateEmail⊕ validateEmail⊕ validatePhone⊕ validatePhone
Record Operators
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }
type Validator = Lift (→) Identity (Either Error)
( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rs
rdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
Record Operators
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }
type Validator = Lift (→) Identity (Either Error)
( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rs
rdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
Record Operators
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }
type Validator = Lift (→) Identity (Either Error)
( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rs
rdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
Record Operators
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }
type Validator = Lift (→) Identity (Either Error)
( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rs
rdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
Record Operators
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }
type Validator = Lift (→) Identity (Either Error)
( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rs
rdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
Compositional Validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }type Validator = Lift (→) Identity (Either Error)( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rsrdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
validateContact :: RecA Validator TotalContact
bobValid :: RecA (Either Error) [Name, Email Work]bobValid = cast validateContact ? bob
validBob :: Either Error (RecA Identity [Name, Email Work])validBob = rdist bobValid
Compositional Validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }type Validator = Lift (→) Identity (Either Error)( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rsrdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
validateContact :: RecA Validator TotalContact
bobValid :: RecA (Either Error) [Name, Email Work]bobValid = cast validateContact ? bob
validBob :: Either Error (RecA Identity [Name, Email Work])validBob = rdist bobValid
Compositional Validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }type Validator = Lift (→) Identity (Either Error)( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rsrdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
validateContact :: RecA Validator TotalContact
bobValid :: RecA (Either Error) [Name, Email Work]
bobValid = cast validateContact ? bob
validBob :: Either Error (RecA Identity [Name, Email Work])validBob = rdist bobValid
Compositional Validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }type Validator = Lift (→) Identity (Either Error)( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rsrdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
validateContact :: RecA Validator TotalContact
bobValid :: RecA (Either Error) [Name, Email Work]bobValid = cast validateContact ? bob
validBob :: Either Error (RecA Identity [Name, Email Work])validBob = rdist bobValid
Compositional Validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }type Validator = Lift (→) Identity (Either Error)( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rsrdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
validateContact :: RecA Validator TotalContact
bobValid :: RecA (Either Error) [Name, Email Work]bobValid = cast validateContact ? bob
validBob :: Either Error (RecA Identity [Name, Email Work])
validBob = rdist bobValid
Compositional Validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }type Validator = Lift (→) Identity (Either Error)( ? ) :: RecU (Lift (→) f g) rs→ RecU f rs→ RecU g rsrdist :: Applicative f⇒ RecU f rs→ f (RecU Identity rs)
validateContact :: RecA Validator TotalContact
bobValid :: RecA (Either Error) [Name, Email Work]bobValid = cast validateContact ? bob
validBob :: Either Error (RecA Identity [Name, Email Work])validBob = rdist bobValid
Laziness as an effect
newtype Identity a = Identity { runIdentity :: a }data Thunk a = Thunk { unThunk :: a }
type PlainRecU rs = RecU Identity rstype LazyRecU rs = RecU Thunk rs
Laziness as an effect
newtype Identity a = Identity { runIdentity :: a }
data Thunk a = Thunk { unThunk :: a }
type PlainRecU rs = RecU Identity rstype LazyRecU rs = RecU Thunk rs
Laziness as an effect
newtype Identity a = Identity { runIdentity :: a }data Thunk a = Thunk { unThunk :: a }
type PlainRecU rs = RecU Identity rstype LazyRecU rs = RecU Thunk rs
Laziness as an effect
newtype Identity a = Identity { runIdentity :: a }data Thunk a = Thunk { unThunk :: a }
type PlainRecU rs = RecU Identity rs
type LazyRecU rs = RecU Thunk rs
Laziness as an effect
newtype Identity a = Identity { runIdentity :: a }data Thunk a = Thunk { unThunk :: a }
type PlainRecU rs = RecU Identity rstype LazyRecU rs = RecU Thunk rs
Concurrent Records with Async
fetchName :: RecA IO ’[Name]fetchName = Name⇐\ someOperation
fetchWorkEmail :: RecA IO ’[Email Work]fetchWorkEmail = Email Work⇐\ anotherOperation
fetchBob :: RecA IO [Name, Email Work]fetchBob = fetchName ⊕ fetchWorkEmail
Concurrent Records with Async
fetchName :: RecA IO ’[Name]
fetchName = Name⇐\ someOperation
fetchWorkEmail :: RecA IO ’[Email Work]fetchWorkEmail = Email Work⇐\ anotherOperation
fetchBob :: RecA IO [Name, Email Work]fetchBob = fetchName ⊕ fetchWorkEmail
Concurrent Records with Async
fetchName :: RecA IO ’[Name]fetchName = Name⇐\ someOperation
fetchWorkEmail :: RecA IO ’[Email Work]fetchWorkEmail = Email Work⇐\ anotherOperation
fetchBob :: RecA IO [Name, Email Work]fetchBob = fetchName ⊕ fetchWorkEmail
Concurrent Records with Async
fetchName :: RecA IO ’[Name]fetchName = Name⇐\ someOperation
fetchWorkEmail :: RecA IO ’[Email Work]
fetchWorkEmail = Email Work⇐\ anotherOperation
fetchBob :: RecA IO [Name, Email Work]fetchBob = fetchName ⊕ fetchWorkEmail
Concurrent Records with Async
fetchName :: RecA IO ’[Name]fetchName = Name⇐\ someOperation
fetchWorkEmail :: RecA IO ’[Email Work]fetchWorkEmail = Email Work⇐\ anotherOperation
fetchBob :: RecA IO [Name, Email Work]fetchBob = fetchName ⊕ fetchWorkEmail
Concurrent Records with Async
fetchName :: RecA IO ’[Name]fetchName = Name⇐\ someOperation
fetchWorkEmail :: RecA IO ’[Email Work]fetchWorkEmail = Email Work⇐\ anotherOperation
fetchBob :: RecA IO [Name, Email Work]
fetchBob = fetchName ⊕ fetchWorkEmail
Concurrent Records with Async
fetchName :: RecA IO ’[Name]fetchName = Name⇐\ someOperation
fetchWorkEmail :: RecA IO ’[Email Work]fetchWorkEmail = Email Work⇐\ anotherOperation
fetchBob :: RecA IO [Name, Email Work]fetchBob = fetchName ⊕ fetchWorkEmail
Concurrent Records with Async
newtype Concurrently a= Concurrently { runConcurrently :: IO a }
( $ ) :: (∀ a. f a→ g a)→ RecU f rs→ RecU g rs
bobConcurrently :: RecA Concurrently [Name, Email Work]bobConcurrently = Concurrently $ fetchBob
concurrentBob :: Concurrently (RecA Identity [...])concurrentBob = rdist bobConcurrently
Concurrent Records with Async
newtype Concurrently a= Concurrently { runConcurrently :: IO a }
( $ ) :: (∀ a. f a→ g a)→ RecU f rs→ RecU g rs
bobConcurrently :: RecA Concurrently [Name, Email Work]bobConcurrently = Concurrently $ fetchBob
concurrentBob :: Concurrently (RecA Identity [...])concurrentBob = rdist bobConcurrently
Concurrent Records with Async
newtype Concurrently a= Concurrently { runConcurrently :: IO a }
( $ ) :: (∀ a. f a→ g a)→ RecU f rs→ RecU g rs
bobConcurrently :: RecA Concurrently [Name, Email Work]bobConcurrently = Concurrently $ fetchBob
concurrentBob :: Concurrently (RecA Identity [...])concurrentBob = rdist bobConcurrently
Concurrent Records with Async
newtype Concurrently a= Concurrently { runConcurrently :: IO a }
( $ ) :: (∀ a. f a→ g a)→ RecU f rs→ RecU g rs
bobConcurrently :: RecA Concurrently [Name, Email Work]
bobConcurrently = Concurrently $ fetchBob
concurrentBob :: Concurrently (RecA Identity [...])concurrentBob = rdist bobConcurrently
Concurrent Records with Async
newtype Concurrently a= Concurrently { runConcurrently :: IO a }
( $ ) :: (∀ a. f a→ g a)→ RecU f rs→ RecU g rs
bobConcurrently :: RecA Concurrently [Name, Email Work]bobConcurrently = Concurrently $ fetchBob
concurrentBob :: Concurrently (RecA Identity [...])concurrentBob = rdist bobConcurrently
Concurrent Records with Async
newtype Concurrently a= Concurrently { runConcurrently :: IO a }
( $ ) :: (∀ a. f a→ g a)→ RecU f rs→ RecU g rs
bobConcurrently :: RecA Concurrently [Name, Email Work]bobConcurrently = Concurrently $ fetchBob
concurrentBob :: Concurrently (RecA Identity [...])
concurrentBob = rdist bobConcurrently
Concurrent Records with Async
newtype Concurrently a= Concurrently { runConcurrently :: IO a }
( $ ) :: (∀ a. f a→ g a)→ RecU f rs→ RecU g rs
bobConcurrently :: RecA Concurrently [Name, Email Work]bobConcurrently = Concurrently $ fetchBob
concurrentBob :: Concurrently (RecA Identity [...])concurrentBob = rdist bobConcurrently
Concurrent Records with Async
fetchBob :: RecA IO [Name, Email Work]bobConcurrently :: RecA Concurrently [Name, Email Work]concurrentBob :: Concurrently (RecA Identity [...])
bob :: IO (RecA Identity [Name, Email Work])bob = runConcurrently concurrentBob
Concurrent Records with Async
fetchBob :: RecA IO [Name, Email Work]bobConcurrently :: RecA Concurrently [Name, Email Work]concurrentBob :: Concurrently (RecA Identity [...])
bob :: IO (RecA Identity [Name, Email Work])bob = runConcurrently concurrentBob
Concurrent Records with Async
fetchBob :: RecA IO [Name, Email Work]bobConcurrently :: RecA Concurrently [Name, Email Work]concurrentBob :: Concurrently (RecA Identity [...])
bob :: IO (RecA Identity [Name, Email Work])
bob = runConcurrently concurrentBob
Concurrent Records with Async
fetchBob :: RecA IO [Name, Email Work]bobConcurrently :: RecA Concurrently [Name, Email Work]concurrentBob :: Concurrently (RecA Identity [...])
bob :: IO (RecA Identity [Name, Email Work])bob = runConcurrently concurrentBob
Containers: The Syntax for Data Types
container : Type
U : Type ElU : U → TypeU / ElU : container
C : containerC.Sh : Type
C U / ElUC.Sh U
C : containerC.Po : C.Sh→ Type
C U / ElUC.Po ElU
Containers: The Syntax for Data Types
container : TypeU : Type ElU : U → TypeU / ElU : container
C : containerC.Sh : Type
C U / ElUC.Sh U
C : containerC.Po : C.Sh→ Type
C U / ElUC.Po ElU
Containers: The Syntax for Data Types
container : TypeU : Type ElU : U → TypeU / ElU : container
C : containerC.Sh : Type
C U / ElUC.Sh U
C : containerC.Po : C.Sh→ Type
C U / ElUC.Po ElU
Containers: The Syntax for Data Types
container : TypeU : Type ElU : U → TypeU / ElU : container
C : containerC.Sh : Type
C U / ElUC.Sh U
C : containerC.Po : C.Sh→ Type
C U / ElUC.Po ElU
Containers: The Syntax for Data Types
container : TypeU : Type ElU : U → TypeU / ElU : container
C : containerC.Sh : Type
C U / ElUC.Sh U
C : containerC.Po : C.Sh→ Type
C U / ElUC.Po ElU
Containers: The Syntax for Data Types
container : TypeU : Type ElU : U → TypeU / ElU : container
C : containerC.Sh : Type
C U / ElUC.Sh U
C : containerC.Po : C.Sh→ Type
C U / ElUC.Po ElU
Restricting Containers
C : container V ⊆ C.ShC|V : container
C U / ElUC|V V / ElU |V
Restricting Containers
C : container V ⊆ C.ShC|V : container
C U / ElUC|V V / ElU |V
Container Lifting
C : container F : Type→ TypeC ↑ F : container
C U / ElUC ↑ F U / F ◦ ElU
Container Lifting
C : container F : Type→ TypeC ↑ F : container
C U / ElUC ↑ F U / F ◦ ElU
A Menagerie of Quantifiers
A Menagerie of Quantifiers
Dependent Products:
Γ ` A : Type Γ, x : A ` B : TypeΓ `
∏AB : Type
Γ, x : A ` e : B[x]
Γ ` λx.e :∏
AB
A Menagerie of Quantifiers
Dependent Sums:
Γ ` A : Type Γ, x : A ` B : TypeΓ `
∑AB : Type
Γ ` a : A Γ ` b : B[a]
Γ ` 〈a, b〉 :∑
AB
A Menagerie of Quantifiers
Inductive Types:
Γ ` A : Type Γ, x : A ` B : TypeΓ `WAB : Type
Γ ` a : A Γ, v : B[a] ` b : WAB
Γ ` sup(a; v. b) : WAB
A Menagerie of Quantifiers
Coinductive Types:
Γ ` A : Type Γ, x : A ` B : TypeΓ ` MAB : Type
Γ ` a : A Γ, v : B[a] ` b :∞ (MAB)
Γ ` inf(a; v. b) : MAB
A Scheme for Quantifiers
Γ, A : Type, (x : A ` B : Type) ` QAB : TypeΓ ` Q quantifier
A Scheme for Quantifiers
Γ, A : Type, (x : A ` B : Type) ` QAB : TypeΓ ` Q quantifier
Quantifiers Give Containers Semantics
Γ, A : Type, (x : A ` B : Type) ` QAB : TypeΓ ` Q quantifier
C : container Q quantifier
JCKQ : Type
C U / ElUJCKQ QUElU
Quantifiers Give Containers Semantics
Γ, A : Type, (x : A ` B : Type) ` QAB : TypeΓ ` Q quantifier
C : container Q quantifier
JCKQ : Type
C U / ElUJCKQ QUElU
Quantifiers Give Containers Semantics
Γ, A : Type, (x : A ` B : Type) ` QAB : TypeΓ ` Q quantifier
C : container Q quantifier
JCKQ : Type
C U / ElUJCKQ QUElU
Vinyl Records as Containers
Records and corecords are finite products and sumsrespectively.
Rec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΠ
CoRec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΣ
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KW
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KM
Vinyl Records as Containers
Records and corecords are finite products and sumsrespectively.
Rec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΠ
CoRec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΣ
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KW
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KM
Vinyl Records as Containers
Records and corecords are finite products and sumsrespectively.
Rec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΠ
CoRec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΣ
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KW
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KM
Vinyl Records as Containers
Records and corecords are finite products and sumsrespectively.
Rec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΠ
CoRec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΣ
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KW
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KM
Vinyl Records as Containers
Records and corecords are finite products and sumsrespectively.
Rec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΠ
CoRec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΣ
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KW
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KM
Vinyl Records as Containers
Records and corecords are finite products and sumsrespectively.
Rec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΠ
CoRec ElU F rs ∼= J(U / ElU)|rs3− ↑ F KΣ
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KW
??? ElU F rs ∼= J(U / ElU)|rs3− ↑ F KM
Questions