galois tech talk / vinyl: records in haskell and type theory

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

Post on 28-May-2015

921 views

Category:

Technology

1 download

Embed Size (px)

DESCRIPTION

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.

TRANSCRIPT

  • 1. Vinyl: Records in Haskell and Type Theory Jon Sterling jonmsterling.com August 12, 2014

2. Records in GHC 7.8 3. Records in GHC 7.8 Haskell records are nominally typed 4. Records in GHC 7.8 Haskell records are nominally typed They may not share eld names 5. Records in GHC 7.8 Haskell records are nominally typed They may not share eld names data R = R { x :: X } 6. Records in GHC 7.8 Haskell records are nominally typed They may not share eld names data R = R { x :: X } data R = R { x :: X } Error 7. Structural typing 8. Structural typing Sharing eld names and accessors 9. Structural typing Sharing eld names and accessors Record types may be characterized structurally 10. Row polymorphism 11. Row polymorphism How do we express the type of a function which adds a eld to a record? 12. Row polymorphism How do we express the type of a function which adds a eld to a record? x : {foo : A} f(x) : {foo : A, bar : B} 13. Row polymorphism How do we express the type of a function which adds a eld to a record? x : {foo : A; rs} f(x) : {foo : A, bar : B; rs} 14. Roll your own in Haskell 15. Roll your own in Haskell data (s :: Symbol) ::: (t :: ) = Field 16. Roll your own in Haskell data (s :: Symbol) ::: (t :: ) = Field data Rec :: [] where 17. Roll your own in Haskell data (s :: Symbol) ::: (t :: ) = Field data Rec :: [] where RNil :: Rec [] 18. Roll your own in Haskell data (s :: Symbol) ::: (t :: ) = Field data Rec :: [] where RNil :: Rec [] (:&) :: !t !(Rec rs) Rec ((s ::: t) : rs) 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. 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. 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. 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. 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. Roll your own in Haskell 25. Roll your own in Haskell f :: Rec (foo ::: A : rs) Rec (bar ::: B : foo ::: A : rs) 26. Why be stringly typed? 27. Why be stringly typed? Lets generalize our key space 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. 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. 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. 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. Actual Type families are not functions, but in many cases can simulate them using Richard Eisenbergs technique outlined in Defunctionalization for the win. data TyFun :: 33. Actual Type families are not functions, but in many cases can simulate them using Richard Eisenbergs technique outlined in Defunctionalization for the win. data TyFun :: type family (f :: TyFun k l ) $ (x :: k) :: l 34. Actual Type families are not functions, but in many cases can simulate them using Richard Eisenbergs 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. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label 36. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label data SLabel :: Label where SHome :: SLabel Home SWork :: SLabel Work 37. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label data SLabel :: Label 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. Example data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label data SLabel :: Label data SAddrKeys :: AddrKeys 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. 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. Sugared example import Data.Singletons as S 43. Sugared example import Data.Singletons as S data Label = Home | Work data AddrKeys = Name | Phone Label | Email Label S.genSingletons [ Label, AddrKeys ] 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. 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. Example records bob :: AddrRec [Name, Email Work] bob = SName =: Robert W. Harper SEmail SWork =: rwh@cs.cmu.edu 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. Recovering HList 49. Recovering HList data Id :: (TyFun k k) where type instance Id $ x = x 50. Recovering HList data Id :: (TyFun k k) where type instance Id $ x = x type HList rs = Rec Id rs 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. Validating records validateName :: String Either Error String validateEmail :: String Either Error String validatePhone :: [N] Either Error [N] 53. Validating records validateName :: String Either Error String validateEmail :: String Either Error String validatePhone :: [N] Either Error [N] *unnnnnhhh...* 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. Welp. 56. Effects inside records data Rec :: (TyFun k ) [k] where RNil :: Rec el [] (:&) :: !(el $ r) !(Rec el rs) Rec el (r : rs) 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. 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. 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. 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. Compositional validation type Validator a = a Either Error a 62. Compositional validation newtype Lift o f g x = Lift { runLift :: f x o g x } type Validator = Lift () Identity (Either Error) 63. Compositional validation newtype Lift o f g x = Lift { runLift :: f x o g x } type Validator = Lift () Identity (Either Error) 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. 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