Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Vinyl: Records in Haskell
and Type Theory
Jon Sterling
jonmsterling.com
August 12, 2014
Records in GHC 7.8
Records in GHC 7.8
Haskell records are nominally typed
Records in GHC 7.8
Haskell records are nominally typed
They may not share field names
Records in GHC 7.8
Haskell records are nominally typed
They may not share field names
data R = R { x :: X }
Records in GHC 7.8
Haskell records are nominally typed
They may not share field names
data R = R { x :: X }
data R’ = R’ { ...
Structural typing
Structural typing
Sharing field names and accessors
Structural typing
Sharing field names and accessors
Record types may be characterized structurally
Row polymorphism
Row polymorphism
How do we express the type of a function which adds a
field to a record?
Row polymorphism
How do we express the type of a function which adds a
field to a record?
x : {foo : A}
f(x) : {foo : A, ba...
Row polymorphism
How do we express the type of a function which adds a
field to a record?
x : {foo : A; rs}
f(x) : {foo : A...
Roll your own in Haskell
Roll your own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
Roll your own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗] → ∗ where
Roll your own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗] → ∗ where
RNil :: Rec ’[]
Roll your own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗] → ∗ where
RNil :: Rec ’[]
(:&) :: !t → !(...
Roll your own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗] → ∗ where
RNil :: Rec ’[]
(:&) :: !t → !(...
Roll your own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗] → ∗ where
RNil :: Rec ’[]
(:&) :: !t → !(...
Roll your own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗] → ∗ where
RNil :: Rec ’[]
(:&) :: !t → !(...
Roll your own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗] → ∗ where
RNil :: Rec ’[]
(:&) :: !t → !(...
Roll your own in Haskell
data (s :: Symbol) ::: (t :: ∗) = Field
data Rec :: [∗] → ∗ where
RNil :: Rec ’[]
(:&) :: !t → !(...
Roll your own in Haskell
Roll your own in Haskell
f :: Rec (”foo” ::: A ’: rs)
→ Rec (”bar” ::: B ’: ”foo” ::: A ’: rs)
Why be stringly typed?
Why be stringly typed?
Let’s generalize our key space
Old
We relied on a single representation for keys as pairs of
strings and types.
data Rec :: [∗] → ∗ where
RNil :: Rec ’[]...
Proposed
We put the keys in an arbitrary type (kind) and describe
their semantics with a function el (for elements).
data ...
Proposed
We put the keys in an arbitrary type (kind) and describe
their semantics with a function el (for elements).
data ...
Proposed
We put the keys in an arbitrary type (kind) and describe
their semantics with a function el (for elements).
data ...
Actual
Type families are not functions, but in many cases can
simulate them using Richard Eisenberg’s technique
outlined i...
Actual
Type families are not functions, but in many cases can
simulate them using Richard Eisenberg’s technique
outlined i...
Actual
Type families are not functions, but in many cases can
simulate them using Richard Eisenberg’s technique
outlined i...
Example
data Label = Home | Work
data AddrKeys = Name | Phone Label | Email Label
Example
data Label = Home | Work
data AddrKeys = Name | Phone Label | Email Label
data SLabel :: Label → ∗ where
SHome :: ...
Example
data Label = Home | Work
data AddrKeys = Name | Phone Label | Email Label
data SLabel :: Label → ∗
Example
data Label = Home | Work
data AddrKeys = Name | Phone Label | Email Label
data SLabel :: Label → ∗
data SAddrKeys ...
Example
data Label = Home | Work
data AddrKeys = Name | Phone Label | Email Label
data SLabel :: Label → ∗
data SAddrKeys ...
Example
data Label = Home | Work
data AddrKeys = Name | Phone Label | Email Label
data SLabel :: Label → ∗
data SAddrKeys ...
Example
data Label = Home | Work
data AddrKeys = Name | Phone Label | Email Label
data SLabel :: Label → ∗
data SAddrKeys ...
Sugared example
import Data.Singletons as S
Sugared example
import Data.Singletons as S
data Label = Home | Work
data AddrKeys = Name | Phone Label | Email Label
S.ge...
Sugared example
import Data.Singletons as S
data Label = Home | Work
data AddrKeys = Name | Phone Label | Email Label
S.ge...
Sugared example
import Data.Singletons as S
data Label = Home | Work
data AddrKeys = Name | Phone Label | Email Label
S.ge...
Example records
bob :: AddrRec [Name, Email Work]
bob = SName =: ”Robert W. Harper”
⊕ SEmail SWork =: ”rwh@cs.cmu.edu”
Example records
bob :: AddrRec [Name, Email Work]
bob = SName =: ”Robert W. Harper”
⊕ SEmail SWork =: ”rwh@cs.cmu.edu”
jon...
Recovering HList
Recovering HList
data Id :: (TyFun k k) → ∗ where
type instance Id $ x = x
Recovering HList
data Id :: (TyFun k k) → ∗ where
type instance Id $ x = x
type HList rs = Rec Id rs
Recovering HList
data Id :: (TyFun k k) → ∗ where
type instance Id $ x = x
type HList rs = Rec Id rs
ex :: HList [Z, Bool,...
Validating records
validateName :: String → Either Error String
validateEmail :: String → Either Error String
validatePhon...
Validating records
validateName :: String → Either Error String
validateEmail :: String → Either Error String
validatePhon...
Validating records
validateName :: String → Either Error String
validateEmail :: String → Either Error String
validatePhon...
Welp.
Effects inside records
data Rec :: (TyFun k ∗ → ∗) → [k] → ∗ where
RNil :: Rec el ’[]
(:&) :: !(el $ r) → !(Rec el rs) → R...
Effects inside records
data Rec :: (TyFun k ∗ → ∗) → (∗ → ∗) → [k] → ∗ where
RNil :: Rec el f ’[]
(:&) :: !(f (el $ r)) → ...
Effects inside records
data Rec :: (TyFun k ∗ → ∗) → (∗ → ∗) → [k] → ∗ where
RNil :: Rec el f ’[]
(:&) :: !(f (el $ r)) → ...
Effects inside records
data Rec :: (TyFun k ∗ → ∗) → (∗ → ∗) → [k] → ∗ where
RNil :: Rec el f ’[]
(:&) :: !(f (el $ r)) → ...
Effects inside records
data Rec :: (TyFun k ∗ → ∗) → (∗ → ∗) → [k] → ∗ where
RNil :: Rec el f ’[]
(:&) :: !(f (el $ r)) → ...
Compositional validation
type Validator a = a → Either Error a
Compositional validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }
type Validator = Lift (→) Identity (Either...
Compositional validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }
type Validator = Lift (→) Identity (Either...
Compositional validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }
type Validator = Lift (→) Identity (Either...
Compositional validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }
type Validator = Lift (→) Identity (Either...
Compositional validation
newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x }
type Validator = Lift (→) Identity (Either...
Record effect operators
Record effect operators
( ) :: Rec el (Lift (→) f g) rs → Rec el f rs → Rec el g rs
Record effect operators
( ) :: Rec el (Lift (→) f g) rs → Rec el f rs → Rec el g rs
rtraverse :: Applicative h ⇒
(∀ x. f x...
Record effect operators
( ) :: Rec el (Lift (→) f g) rs → Rec el f rs → Rec el g rs
rtraverse :: Applicative h ⇒
(∀ x. f x...
Compositional validation
bob :: AddrRec [Name, Email Work]
validateContact :: AddrRec Validator TotalContact
Compositional validation
bob :: AddrRec [Name, Email Work]
validateContact :: AddrRec Validator TotalContact
bobValid :: A...
Compositional validation
bob :: AddrRec [Name, Email Work]
validateContact :: AddrRec Validator TotalContact
bobValid :: A...
Laziness as an effect
Laziness as an effect
newtype Identity a = Identity { runIdentity :: a }
data Thunk a = Thunk { unThunk :: a }
Laziness as an effect
newtype Identity a = Identity { runIdentity :: a }
data Thunk a = Thunk { unThunk :: a }
type PlainR...
Laziness as an effect
newtype Identity a = Identity { runIdentity :: a }
data Thunk a = Thunk { unThunk :: a }
type PlainR...
Concurrent records with Async
Concurrent records with Async
fetchName :: AddrRec IO ’[Name]
fetchName = SName ⇐ runDB nameQuery
Concurrent records with Async
fetchName :: AddrRec IO ’[Name]
fetchName = SName ⇐ runDB nameQuery
fetchWorkEmail :: AddrRe...
Concurrent records with Async
fetchName :: AddrRec IO ’[Name]
fetchName = SName ⇐ runDB nameQuery
fetchWorkEmail :: AddrRe...
Concurrent records with Async
Concurrent records with Async
newtype Concurrently a
= Concurrently { runConcurrently :: IO a }
Concurrent records with Async
newtype Concurrently a
= Concurrently { runConcurrently :: IO a }
( $ ) :: (∀ a. f a → g a) ...
Concurrent records with Async
newtype Concurrently a
= Concurrently { runConcurrently :: IO a }
( $ ) :: (∀ a. f a → g a) ...
Concurrent records with Async
newtype Concurrently a
= Concurrently { runConcurrently :: IO a }
( $ ) :: (∀ a. f a → g a) ...
Type Theoretic Semantics for Records
Universes `a la Tarski
Universes `a la Tarski
A type U of codes for types.
Universes `a la Tarski
A type U of codes for types.
Function ElU : U → Type.
Universes `a la Tarski
A type U of codes for types.
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
Records as products
Records as products
Records: the product of the image of ElU in Type
restricted to a subset of U.
Records as products

Type
Records as products

Type
×
×
×
×
Vinyl: beyond records?
Vinyl: beyond records?
Records and corecords are finite products and sums
respectively.
Vinyl: beyond records?
Records and corecords are finite products and sums
respectively.
Rec(ElU ; F; rs) :≡
U|rs
F ◦ ElU
Vinyl: beyond records?
Records and corecords are finite products and sums
respectively.
Rec(ElU ; F; rs) :≡
U|rs
F ◦ ElU
Co...
Vinyl: beyond records?
Records and corecords are finite products and sums
respectively.
Rec(ElU ; F; rs) :≡
U|rs
F ◦ ElU
Co...
Vinyl: beyond records?
Records and corecords are finite products and sums
respectively.
Rec(ElU ; F; rs) :≡
U|rs
F ◦ ElU
Co...
Vinyl: beyond records?
(U|rs) (F ◦ ElU )
Vinyl: beyond records?
(U|rs) (F ◦ ElU ) Π
Vinyl: beyond records?
(U|rs) (F ◦ ElU ) W
Vinyl: beyond records?
(U|rs) (F ◦ ElU ) M
Presheaves
Presheaves
A presheaf on some space X is a functor
O(X)op
→ Type, where O is the category of open sets of
X for whatever t...
Topologies on some space X
Topologies on some space X
What are the open sets on X?
Topologies on some space X
What are the open sets on X?
The empty set and X are open sets
Topologies on some space X
What are the open sets on X?
The empty set and X are open sets
The union of open sets is open
Topologies on some space X
What are the open sets on X?
The empty set and X are open sets
The union of open sets is open
F...
Records are presheaves
Records are presheaves
Let O = P, the discrete topology
Records are presheaves
Let O = P, the discrete topology
Then records on a universe X give rise to a presheaf
R: subset inc...
Records are presheaves
Let O = P, the discrete topology
Then records on a universe X give rise to a presheaf
R: subset inc...
Records are presheaves
Let O = P, the discrete topology
Then records on a universe X give rise to a presheaf
R: subset inc...
Records are sheaves
Records are sheaves
For a cover U = i Ui on X, then:
R(U) i R(Ui) i,j R(Ui ∩ Uj)
e p
q
is an equalizer, where
e = λr.λi. c...
Records are sheaves
For a cover U = i Ui on X, then:
R(U) i R(Ui) i,j R(Ui ∩ Uj)
Γ
e
m
!u
p
q
where
e = λr.λi. castUi
(r)
...
Records with non-trivial topology
Records with non-trivial topology
NameType :≡ {F, M, L}
Records with non-trivial topology
NameType :≡ {F, M, L}
A :≡ {Name[t] | t ∈ NameType} ∪ {Phone[ ] | ∈ Label}
Records with non-trivial topology
NameType :≡ {F, M, L}
A :≡ {Name[t] | t ∈ NameType} ∪ {Phone[ ] | ∈ Label}
ElA :≡ λ .Str...
Records with non-trivial topology
NameType :≡ {F, M, L}
A :≡ {Name[t] | t ∈ NameType} ∪ {Phone[ ] | ∈ Label}
ElA :≡ λ .Str...
Records with non-trivial topology
NameType :≡ {F, M, L}
A :≡ {Name[t] | t ∈ NameType} ∪ {Phone[ ] | ∈ Label}
ElA :≡ λ .Str...
Records with non-trivial topology
NameType :≡ {F, M, L}
A :≡ {Name[t] | t ∈ NameType} ∪ {Phone[ ] | ∈ Label}
ElA :≡ λ .Str...
Future work
Future work
Complete: formalization of records with topologies as
presheaves in Coq
Future work
Complete: formalization of records with topologies as
presheaves in Coq
In Progress: formalization of records ...
Future work
Complete: formalization of records with topologies as
presheaves in Coq
In Progress: formalization of records ...
Questions
Upcoming SlideShare
Loading in …5
×
Upcoming SlideShare
Phone Apps... para el teléfono de escritorio
Next
Download to read offline and view in fullscreen.

4

Share

Download to read offline

Galois Tech Talk / Vinyl: Records in Haskell and Type Theory

Download to read offline

Records in Haskell are notoriously difficult to compose; many solutions have been proposed. Vinyl lies in the space of library-level approaches, and addresses polymorphism, extensibility, effects and strictness. I describe how Vinyl approaches record families over arbitrary key spaces using a Tarski universe construction, as well as a method for immersing each field of a record in a chosen effect modality. Also discussed are presheaves, sheaves and containers.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Galois Tech Talk / Vinyl: Records in Haskell and Type Theory

  1. 1. Vinyl: Records in Haskell and Type Theory Jon Sterling jonmsterling.com August 12, 2014
  2. 2. Records in GHC 7.8
  3. 3. Records in GHC 7.8 Haskell records are nominally typed
  4. 4. Records in GHC 7.8 Haskell records are nominally typed They may not share field names
  5. 5. Records in GHC 7.8 Haskell records are nominally typed They may not share field names data R = R { x :: X }
  6. 6. Records in GHC 7.8 Haskell records are nominally typed They may not share field names data R = R { x :: X } data R’ = R’ { x :: X } −− ˆ Error
  7. 7. Structural typing
  8. 8. Structural typing Sharing field names and accessors
  9. 9. Structural typing Sharing field names and accessors Record types may be characterized structurally
  10. 10. Row polymorphism
  11. 11. Row polymorphism How do we express the type of a function which adds a field to a record?
  12. 12. Row polymorphism How do we express the type of a function which adds a field to a record? x : {foo : A} f(x) : {foo : A, bar : B}
  13. 13. Row polymorphism How do we express the type of a function which adds a field to a record? x : {foo : A; rs} f(x) : {foo : A, bar : B; rs}
  14. 14. Roll your own in Haskell
  15. 15. Roll your own in Haskell data (s :: Symbol) ::: (t :: ∗) = Field
  16. 16. Roll your own in Haskell data (s :: Symbol) ::: (t :: ∗) = Field data Rec :: [∗] → ∗ where
  17. 17. Roll your own in Haskell data (s :: Symbol) ::: (t :: ∗) = Field data Rec :: [∗] → ∗ where RNil :: Rec ’[]
  18. 18. Roll your own in Haskell data (s :: Symbol) ::: (t :: ∗) = Field data Rec :: [∗] → ∗ where RNil :: Rec ’[] (:&) :: !t → !(Rec rs) → Rec ((s ::: t) ’: rs)
  19. 19. 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 :: [∗])
  20. 20. 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
  21. 21. 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]
  22. 22. 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)
  23. 23. 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
  24. 24. Roll your own in Haskell
  25. 25. Roll your own in Haskell f :: Rec (”foo” ::: A ’: rs) → Rec (”bar” ::: B ’: ”foo” ::: A ’: rs)
  26. 26. Why be stringly typed?
  27. 27. Why be stringly typed? Let’s generalize our key space
  28. 28. Old We relied on a single representation for keys as pairs of strings and types. data Rec :: [∗] → ∗ where RNil :: Rec ’[] (:&) :: !t → !(Rec rs) → Rec ((s ::: t) ’: rs)
  29. 29. Proposed We put the keys in an arbitrary type (kind) and describe their semantics with a function el (for elements). data Rec :: [∗] → ∗ where RNil :: Rec ’[] (:&) :: !t → !(Rec rs) → Rec ((s ::: t) ’: rs)
  30. 30. Proposed We put the keys in an arbitrary type (kind) and describe their semantics with a function el (for elements). data Rec :: (el :: k → ∗) → (rs :: [k]) → ∗ where RNil :: Rec el ’[] (:&) :: ∀(r :: k) (rs’:: [k]). !(el r) → !(Rec el rs) → Rec (r ’: rs’)
  31. 31. Proposed We put the keys in an arbitrary type (kind) and describe their semantics with a function el (for elements). data Rec :: (k → ∗) → [k] → ∗ where RNil :: Rec el ’[] (:&) :: !(el r) → !(Rec el rs) → Rec (r ’: rs)
  32. 32. Actual Type families are not functions, but in many cases can simulate them using Richard Eisenberg’s technique outlined in Defunctionalization for the win. data TyFun :: ∗ → ∗ → ∗
  33. 33. Actual Type families are not functions, but in many cases can simulate them using Richard Eisenberg’s technique outlined in Defunctionalization for the win. data TyFun :: ∗ → ∗ → ∗ type family (f :: TyFun k l → ∗) $ (x :: k) :: l
  34. 34. Actual Type families are not functions, but in many cases can simulate them using Richard Eisenberg’s technique outlined in Defunctionalization for the win. data TyFun :: ∗ → ∗ → ∗ type family (f :: TyFun k l → ∗) $ (x :: k) :: l data Rec :: (TyFun k ∗ → ∗) → [k] → ∗ where RNil :: Rec el ’[] (:&) :: !(el $ r) → !(Rec el rs) → Rec el (r ’: rs)
  35. 35. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label
  36. 36. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label data SLabel :: Label → ∗ where SHome :: SLabel Home SWork :: SLabel Work
  37. 37. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label data SLabel :: Label → ∗
  38. 38. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label data SLabel :: Label → ∗ data SAddrKeys :: AddrKeys → ∗ where SName :: SAddrKeys Name SPhone :: SLabel l → SAddrKeys (Phone l) SEmail :: SLabel l → SAddrKeys (Email l)
  39. 39. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label data SLabel :: Label → ∗ data SAddrKeys :: AddrKeys → ∗
  40. 40. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label data SLabel :: Label → ∗ data SAddrKeys :: AddrKeys → ∗ data ElAddr :: (TyFun AddrKeys ∗) → ∗ where ElAddr :: ElAddr el
  41. 41. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label data SLabel :: Label → ∗ data SAddrKeys :: AddrKeys → ∗ data ElAddr :: (TyFun AddrKeys ∗) → ∗ where ElAddr :: ElAddr el type instance ElAddr $ Name = String type instance ElAddr $ (Phone l) = [N] type instance ElAddr $ (Email l) = String type AddrRec rs = Rec ElAddr rs
  42. 42. Sugared example import Data.Singletons as S
  43. 43. Sugared example import Data.Singletons as S data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label S.genSingletons [ ’’Label, ’’AddrKeys ]
  44. 44. Sugared example import Data.Singletons as S data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label S.genSingletons [ ’’Label, ’’AddrKeys ] makeUniverse ’’AddrKeys ”ElAddr”
  45. 45. Sugared example import Data.Singletons as S data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label S.genSingletons [ ’’Label, ’’AddrKeys ] makeUniverse ’’AddrKeys ”ElAddr” type instance ElAddr $ Name = String type instance ElAddr $ (Phone l) = [N] type instance ElAddr $ (Email l) = String type AddrRec rs = Rec ElAddr rs
  46. 46. Example records bob :: AddrRec [Name, Email Work] bob = SName =: ”Robert W. Harper” ⊕ SEmail SWork =: ”rwh@cs.cmu.edu”
  47. 47. Example records bob :: AddrRec [Name, Email Work] bob = SName =: ”Robert W. Harper” ⊕ SEmail SWork =: ”rwh@cs.cmu.edu” jon :: AddrRec [Name, Email Work, Email Home] jon = SName =: ”Jon M. Sterling” ⊕ SEmail SWork =: ”jon@fobo.net” ⊕ SEmail SHome =: ”jon@jonmsterling.com”
  48. 48. Recovering HList
  49. 49. Recovering HList data Id :: (TyFun k k) → ∗ where type instance Id $ x = x
  50. 50. Recovering HList data Id :: (TyFun k k) → ∗ where type instance Id $ x = x type HList rs = Rec Id rs
  51. 51. Recovering HList data Id :: (TyFun k k) → ∗ where type instance Id $ x = x type HList rs = Rec Id rs ex :: HList [Z, Bool, String] ex = 34 :& True :& ”vinyl” :& RNil
  52. 52. Validating records validateName :: String → Either Error String validateEmail :: String → Either Error String validatePhone :: [N] → Either Error [N]
  53. 53. Validating records validateName :: String → Either Error String validateEmail :: String → Either Error String validatePhone :: [N] → Either Error [N] *unnnnnhhh...*
  54. 54. Validating records validateName :: String → Either Error String validateEmail :: String → Either Error String validatePhone :: [N] → Either Error [N] *unnnnnhhh...* validateContact :: AddrRec [Name, Email Work] → Either Error (AddrRec [Name, Email Work])
  55. 55. Welp.
  56. 56. Effects inside records data Rec :: (TyFun k ∗ → ∗) → [k] → ∗ where RNil :: Rec el ’[] (:&) :: !(el $ r) → !(Rec el rs) → Rec el (r ’: rs)
  57. 57. Effects inside records data Rec :: (TyFun k ∗ → ∗) → (∗ → ∗) → [k] → ∗ where RNil :: Rec el f ’[] (:&) :: !(f (el $ r)) → !(Rec el f rs) → Rec el f (r ’: rs)
  58. 58. Effects inside records data Rec :: (TyFun k ∗ → ∗) → (∗ → ∗) → [k] → ∗ where RNil :: Rec el f ’[] (:&) :: !(f (el $ r)) → !(Rec el f rs) → Rec el f (r ’: rs)
  59. 59. Effects inside records data Rec :: (TyFun k ∗ → ∗) → (∗ → ∗) → [k] → ∗ where RNil :: Rec el f ’[] (:&) :: !(f (el $ r)) → !(Rec el f rs) → Rec el f (r ’: rs) (=:) : Applicative f ⇒ sing r → el $ r → Rec el f ’[r] k =: x = pure x :& RNil
  60. 60. Effects inside records data Rec :: (TyFun k ∗ → ∗) → (∗ → ∗) → [k] → ∗ where RNil :: Rec el f ’[] (:&) :: !(f (el $ r)) → !(Rec el f rs) → Rec el f (r ’: rs) (=:) : Applicative f ⇒ sing r → el $ r → Rec el f ’[r] k =: x = pure x :& RNil (⇐): sing r → f (el $ r) → Rec el f ’[r] k ⇐ x = x :& RNil
  61. 61. Compositional validation type Validator a = a → Either Error a
  62. 62. Compositional validation newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x } type Validator = Lift (→) Identity (Either Error)
  63. 63. Compositional validation newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x } type Validator = Lift (→) Identity (Either Error)
  64. 64. Compositional validation newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x } type Validator = Lift (→) Identity (Either Error) validateName :: AddrRec Validator ’[Name] validatePhone :: ∀l. AddrRec Validator ’[Phone l] validateEmail :: ∀l. AddrRec Validator ’[Email l]
  65. 65. Compositional validation newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x } type Validator = Lift (→) Identity (Either Error) validateName :: AddrRec Validator ’[Name] validatePhone :: ∀l. AddrRec Validator ’[Phone l] validateEmail :: ∀l. AddrRec Validator ’[Email l] type TotalContact = [ Name, Email Home, Email Work , Phone Home, Phone Work ]
  66. 66. Compositional validation newtype Lift o f g x = Lift { runLift :: f x ‘o‘ g x } type Validator = Lift (→) Identity (Either Error) validateName :: AddrRec Validator ’[Name] validatePhone :: ∀l. AddrRec Validator ’[Phone l] validateEmail :: ∀l. AddrRec Validator ’[Email l] type TotalContact = [ Name, Email Home, Email Work , Phone Home, Phone Work ] validateContact :: AddrRec Validator TotalContact validateContact = validateName ⊕ validateEmail ⊕ validateEmail ⊕ validatePhone ⊕ validatePhone
  67. 67. Record effect operators
  68. 68. Record effect operators ( ) :: Rec el (Lift (→) f g) rs → Rec el f rs → Rec el g rs
  69. 69. Record effect operators ( ) :: Rec el (Lift (→) f g) rs → Rec el f rs → Rec el g rs rtraverse :: Applicative h ⇒ (∀ x. f x → h (g x)) → Rec el f rs → h (Rec el g rs)
  70. 70. Record effect operators ( ) :: Rec el (Lift (→) f g) rs → Rec el f rs → Rec el g rs rtraverse :: Applicative h ⇒ (∀ x. f x → h (g x)) → Rec el f rs → h (Rec el g rs) rdist :: Applicative f ⇒ Rec el f rs → f (Rec el Identity rs) rdist = rtraverse (fmap Identity)
  71. 71. Compositional validation bob :: AddrRec [Name, Email Work] validateContact :: AddrRec Validator TotalContact
  72. 72. Compositional validation bob :: AddrRec [Name, Email Work] validateContact :: AddrRec Validator TotalContact bobValid :: AddrRec (Either Error) [Name, Email Work] bobValid = cast validateContact bob
  73. 73. Compositional validation bob :: AddrRec [Name, Email Work] validateContact :: AddrRec Validator TotalContact bobValid :: AddrRec (Either Error) [Name, Email Work] bobValid = cast validateContact bob validBob :: Either Error (AddrRec Identity [Name, Email Work]) validBob = rdist bobValid
  74. 74. Laziness as an effect
  75. 75. Laziness as an effect newtype Identity a = Identity { runIdentity :: a } data Thunk a = Thunk { unThunk :: a }
  76. 76. Laziness as an effect newtype Identity a = Identity { runIdentity :: a } data Thunk a = Thunk { unThunk :: a } type PlainRec el rs = Rec el Identity rs
  77. 77. Laziness as an effect newtype Identity a = Identity { runIdentity :: a } data Thunk a = Thunk { unThunk :: a } type PlainRec el rs = Rec el Identity rs type LazyRec el rs = Rec el Thunk rs
  78. 78. Concurrent records with Async
  79. 79. Concurrent records with Async fetchName :: AddrRec IO ’[Name] fetchName = SName ⇐ runDB nameQuery
  80. 80. Concurrent records with Async fetchName :: AddrRec IO ’[Name] fetchName = SName ⇐ runDB nameQuery fetchWorkEmail :: AddrRec IO ’[Email Work] fetchWorkEmail = SEmail SWork ⇐ runDB emailQuery
  81. 81. Concurrent records with Async fetchName :: AddrRec IO ’[Name] fetchName = SName ⇐ runDB nameQuery fetchWorkEmail :: AddrRec IO ’[Email Work] fetchWorkEmail = SEmail SWork ⇐ runDB emailQuery fetchBob :: AddrRec IO [Name, Email Work] fetchBob = fetchName ⊕ fetchWorkEmail
  82. 82. Concurrent records with Async
  83. 83. Concurrent records with Async newtype Concurrently a = Concurrently { runConcurrently :: IO a }
  84. 84. Concurrent records with Async newtype Concurrently a = Concurrently { runConcurrently :: IO a } ( $ ) :: (∀ a. f a → g a) → Rec el f rs → Rec el g rs
  85. 85. Concurrent records with Async newtype Concurrently a = Concurrently { runConcurrently :: IO a } ( $ ) :: (∀ a. f a → g a) → Rec el f rs → Rec el g rs bobConcurrently :: Rec el Concurrently [Name, Email Work] bobConcurrently = Concurrently $ fetchBob
  86. 86. Concurrent records with Async newtype Concurrently a = Concurrently { runConcurrently :: IO a } ( $ ) :: (∀ a. f a → g a) → Rec el f rs → Rec el g rs bobConcurrently :: Rec el Concurrently [Name, Email Work] bobConcurrently = Concurrently $ fetchBob concurrentBob :: IO (PlainRec el [Name, Email Work]) concurrentBob = runConcurrently (rdist bobConcurrently)
  87. 87. Type Theoretic Semantics for Records
  88. 88. Universes `a la Tarski
  89. 89. Universes `a la Tarski A type U of codes for types.
  90. 90. Universes `a la Tarski A type U of codes for types. Function ElU : U → Type.
  91. 91. Universes `a la Tarski A type U of codes for types. Function ElU : U → Type. Γ s : U Γ ElU (s) : Type
  92. 92. Universes `a la Tarski Type
  93. 93. Universes `a la Tarski  Type
  94. 94. Universes `a la Tarski  Type
  95. 95. Universes `a la Tarski  Type
  96. 96. Records as products
  97. 97. Records as products Records: the product of the image of ElU in Type restricted to a subset of U.
  98. 98. Records as products  Type
  99. 99. Records as products  Type × × × ×
  100. 100. Vinyl: beyond records?
  101. 101. Vinyl: beyond records? Records and corecords are finite products and sums respectively.
  102. 102. Vinyl: beyond records? Records and corecords are finite products and sums respectively. Rec(ElU ; F; rs) :≡ U|rs F ◦ ElU
  103. 103. Vinyl: beyond records? Records and corecords are finite products and sums respectively. Rec(ElU ; F; rs) :≡ U|rs F ◦ ElU CoRec(ElU ; F; rs) :≡ U|rs F ◦ ElU
  104. 104. Vinyl: beyond records? Records and corecords are finite products and sums respectively. Rec(ElU ; F; rs) :≡ U|rs F ◦ ElU CoRec(ElU ; F; rs) :≡ U|rs F ◦ ElU Data(ElU ; F; rs) :≡ WU|rs F ◦ ElU
  105. 105. Vinyl: beyond records? Records and corecords are finite products and sums respectively. Rec(ElU ; F; rs) :≡ U|rs F ◦ ElU CoRec(ElU ; F; rs) :≡ U|rs F ◦ ElU Data(ElU ; F; rs) :≡ WU|rs F ◦ ElU Codata(ElU ; F; rs) :≡ MU|rs F ◦ ElU
  106. 106. Vinyl: beyond records? (U|rs) (F ◦ ElU )
  107. 107. Vinyl: beyond records? (U|rs) (F ◦ ElU ) Π
  108. 108. Vinyl: beyond records? (U|rs) (F ◦ ElU ) W
  109. 109. Vinyl: beyond records? (U|rs) (F ◦ ElU ) M
  110. 110. Presheaves
  111. 111. Presheaves A presheaf on some space X is a functor O(X)op → Type, where O is the category of open sets of X for whatever topology you have chosen.
  112. 112. Topologies on some space X
  113. 113. Topologies on some space X What are the open sets on X?
  114. 114. Topologies on some space X What are the open sets on X? The empty set and X are open sets
  115. 115. Topologies on some space X What are the open sets on X? The empty set and X are open sets The union of open sets is open
  116. 116. Topologies on some space X What are the open sets on X? The empty set and X are open sets The union of open sets is open Finite intersections of open sets are open
  117. 117. Records are presheaves
  118. 118. Records are presheaves Let O = P, the discrete topology
  119. 119. Records are presheaves Let O = P, the discrete topology Then records on a universe X give rise to a presheaf R: subset inclusions are taken to casts from larger to smaller records
  120. 120. Records are presheaves Let O = P, the discrete topology Then records on a universe X give rise to a presheaf R: subset inclusions are taken to casts from larger to smaller records for U ∈ P(X) R(U) :≡ U ElX|U : Type
  121. 121. Records are presheaves Let O = P, the discrete topology Then records on a universe X give rise to a presheaf R: subset inclusions are taken to casts from larger to smaller records for U ∈ P(X) R(U) :≡ U ElX|U : Type for i : V → U R(i) :≡ cast : R(U) → R(V )
  122. 122. Records are sheaves
  123. 123. Records are sheaves For a cover U = i Ui on X, then: R(U) i R(Ui) i,j R(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))
  124. 124. Records are sheaves For a cover U = i Ui on X, then: R(U) i R(Ui) i,j R(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))
  125. 125. Records with non-trivial topology
  126. 126. Records with non-trivial topology NameType :≡ {F, M, L}
  127. 127. Records with non-trivial topology NameType :≡ {F, M, L} A :≡ {Name[t] | t ∈ NameType} ∪ {Phone[ ] | ∈ Label}
  128. 128. Records with non-trivial topology NameType :≡ {F, M, L} A :≡ {Name[t] | t ∈ NameType} ∪ {Phone[ ] | ∈ Label} ElA :≡ λ .String
  129. 129. Records with non-trivial topology NameType :≡ {F, M, L} A :≡ {Name[t] | t ∈ NameType} ∪ {Phone[ ] | ∈ Label} ElA :≡ λ .String T :≡ {U ∈ P(A) | Name[M] ∈ U ⇒ {Name[F], Name[L]} ⊆ U}
  130. 130. Records with non-trivial topology NameType :≡ {F, M, L} A :≡ {Name[t] | t ∈ NameType} ∪ {Phone[ ] | ∈ Label} ElA :≡ λ .String T :≡ {U ∈ P(A) | Name[M] ∈ U ⇒ {Name[F], Name[L]} ⊆ U} ex : RT ({Name[t] | t ∈ NameType}) ex :≡ {Name[F] → ”Robert”; Name[M] → ”W”; Name[L] → ”Harper”}
  131. 131. Records with non-trivial topology NameType :≡ {F, M, L} A :≡ {Name[t] | t ∈ NameType} ∪ {Phone[ ] | ∈ Label} ElA :≡ λ .String T :≡ {U ∈ P(A) | Name[M] ∈ U ⇒ {Name[F], Name[L]} ⊆ U} ex : RT ({Name[t] | t ∈ NameType}) ex :≡ {Name[F] → ”Robert”; Name[M] → ”W”; Name[L] → ”Harper”} nope : RT ({Name[M], Phone[Work]}) nope :≡ {Name[M] → ”W”; Phone[Work] → ”5555555555”}
  132. 132. Future work
  133. 133. Future work Complete: formalization of records with topologies as presheaves in Coq
  134. 134. Future work Complete: formalization of records with topologies as presheaves in Coq In Progress: formalization of records as sheaves
  135. 135. Future work Complete: formalization of records with topologies as presheaves in Coq In Progress: formalization of records as sheaves Future: extension to dependent records using extensional type theory and realizability (Nuprl, MetaPRL)
  136. 136. Questions
  • yanana

    Dec. 3, 2015
  • adamszlachta

    Apr. 21, 2015
  • DanyelleKoch

    Apr. 4, 2015
  • manojkumrm

    Aug. 12, 2014

Records in Haskell are notoriously difficult to compose; many solutions have been proposed. Vinyl lies in the space of library-level approaches, and addresses polymorphism, extensibility, effects and strictness. I describe how Vinyl approaches record families over arbitrary key spaces using a Tarski universe construction, as well as a method for immersing each field of a record in a chosen effect modality. Also discussed are presheaves, sheaves and containers.

Views

Total views

2,178

On Slideshare

0

From embeds

0

Number of embeds

89

Actions

Downloads

18

Shares

0

Comments

0

Likes

4

×