Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Haskell's Kind System - A Primer

Haskell's Kind System - A Primer

A primer on Type Level programming. My Presentation of the excellent article at https://diogocastro.com/blog/2018/10/17/haskells-kind-system-a-primer/

Tommaso Piazza

November 01, 2018
Tweet

More Decks by Tommaso Piazza

Other Decks in Programming

Transcript

  1. Haskell's Kind System A primer https://diogocastro.com/blog/2018/10/17/haskells-kind-system-a-primer Berlin - Haskell Meetup

    1 Nov 2018 © Tommaso Piazza, 2018 - https://github.com/blender 1
  2. Types We all have seen types & values before ©

    Tommaso Piazza, 2018 - https://github.com/blender 2
  3. Types We all have seen types & values before —

    :t True © Tommaso Piazza, 2018 - https://github.com/blender 2
  4. Types We all have seen types & values before —

    :t True — Bool ✅ © Tommaso Piazza, 2018 - https://github.com/blender 2
  5. Types We all have seen types & values before —

    :t True — Bool ✅ — :t "Hello" © Tommaso Piazza, 2018 - https://github.com/blender 2
  6. Types We all have seen types & values before —

    :t True — Bool ✅ — :t "Hello" — String ✅ © Tommaso Piazza, 2018 - https://github.com/blender 2
  7. Types We all have seen types & values before —

    :t True — Bool ✅ — :t "Hello" — String ✅ — :t (+) © Tommaso Piazza, 2018 - https://github.com/blender 2
  8. Types We all have seen types & values before —

    :t True — Bool ✅ — :t "Hello" — String ✅ — :t (+) — Num a => a -> a -> a ✅ © Tommaso Piazza, 2018 - https://github.com/blender 2
  9. Kinds are to types as types are to values ©

    Tommaso Piazza, 2018 - https://github.com/blender 3
  10. Kinds are to types as types are to values All

    inhabited types have kind * © Tommaso Piazza, 2018 - https://github.com/blender 4
  11. Kinds are to types as types are to values All

    inhabited types have kind * — :k Bool © Tommaso Piazza, 2018 - https://github.com/blender 4
  12. Kinds are to types as types are to values All

    inhabited types have kind * — :k Bool — * © Tommaso Piazza, 2018 - https://github.com/blender 4
  13. Kinds are to types as types are to values All

    inhabited types have kind * — :k Bool — * — :k String © Tommaso Piazza, 2018 - https://github.com/blender 4
  14. Kinds are to types as types are to values All

    inhabited types have kind * — :k Bool — * — :k String — * © Tommaso Piazza, 2018 - https://github.com/blender 4
  15. Kinds are to types as types are to values All

    inhabited types have kind * — :k Bool — * — :k String — * — :k [Int] © Tommaso Piazza, 2018 - https://github.com/blender 4
  16. Kinds are to types as types are to values All

    inhabited types have kind * — :k Bool — * — :k String — * — :k [Int] — * © Tommaso Piazza, 2018 - https://github.com/blender 4
  17. Not all types are inhabited © Tommaso Piazza, 2018 -

    https://github.com/blender 5
  18. Not all types are inhabited — Just 1 :: Maybe

    © Tommaso Piazza, 2018 - https://github.com/blender 5
  19. Not all types are inhabited — Just 1 :: Maybe

    — ❌ Expecting one more argument to ‘Maybe’ © Tommaso Piazza, 2018 - https://github.com/blender 5
  20. Not all types are inhabited — Just 1 :: Maybe

    — ❌ Expecting one more argument to ‘Maybe’ — Right 1 :: Either © Tommaso Piazza, 2018 - https://github.com/blender 5
  21. Not all types are inhabited — Just 1 :: Maybe

    — ❌ Expecting one more argument to ‘Maybe’ — Right 1 :: Either — ❌ Expecting two more arguments to ‘Either’ © Tommaso Piazza, 2018 - https://github.com/blender 5
  22. Not all types are inhabited — Just 1 :: Maybe

    — ❌ Expecting one more argument to ‘Maybe’ — Right 1 :: Either — ❌ Expecting two more arguments to ‘Either’ — What are Either and Maybe ? © Tommaso Piazza, 2018 - https://github.com/blender 5
  23. Constructors Let's talk about Data Constructors data Person = MkPerson

    { name :: String, age :: Int } deriving Show © Tommaso Piazza, 2018 - https://github.com/blender 6
  24. Constructors Let's talk about Data Constructors data Person = MkPerson

    { name :: String, age :: Int } deriving Show — 2 Arguments © Tommaso Piazza, 2018 - https://github.com/blender 6
  25. Constructors Let's talk about Data Constructors data Person = MkPerson

    { name :: String, age :: Int } deriving Show — 2 Arguments — MkPerson :: String -> Int -> Person © Tommaso Piazza, 2018 - https://github.com/blender 6
  26. Constructors Let's talk about Data Constructors data Person = MkPerson

    { name :: String, age :: Int } deriving Show — 2 Arguments — MkPerson :: String -> Int -> Person — :t MKPerson "Tommaso" © Tommaso Piazza, 2018 - https://github.com/blender 6
  27. Constructors Let's talk about Data Constructors data Person = MkPerson

    { name :: String, age :: Int } deriving Show — 2 Arguments — MkPerson :: String -> Int -> Person — :t MKPerson "Tommaso" — MKPerson "Tommaso" :: Int -> Person © Tommaso Piazza, 2018 - https://github.com/blender 6
  28. Constructors (2) Type Constrcutors data Either a b = Left

    a | Right b -- *_____▾_____* -- Type Constructor © Tommaso Piazza, 2018 - https://github.com/blender 7
  29. Constructors (2) Type Constrcutors data Either a b = Left

    a | Right b -- *_____▾_____* -- Type Constructor — :k Either String Int © Tommaso Piazza, 2018 - https://github.com/blender 7
  30. Constructors (2) Type Constrcutors data Either a b = Left

    a | Right b -- *_____▾_____* -- Type Constructor — :k Either String Int — * © Tommaso Piazza, 2018 - https://github.com/blender 7
  31. Constructors (2) Type Constrcutors data Either a b = Left

    a | Right b -- *_____▾_____* -- Type Constructor — :k Either String Int — * — :k Either String © Tommaso Piazza, 2018 - https://github.com/blender 7
  32. Constructors (2) Type Constrcutors data Either a b = Left

    a | Right b -- *_____▾_____* -- Type Constructor — :k Either String Int — * — :k Either String — * -> * © Tommaso Piazza, 2018 - https://github.com/blender 7
  33. Constructors (2) Type Constrcutors data Either a b = Left

    a | Right b -- *_____▾_____* -- Type Constructor — :k Either String Int — * — :k Either String — * -> * — :k Either © Tommaso Piazza, 2018 - https://github.com/blender 7
  34. Constructors (2) Type Constrcutors data Either a b = Left

    a | Right b -- *_____▾_____* -- Type Constructor — :k Either String Int — * — :k Either String — * -> * — :k Either — * -> * © Tommaso Piazza, 2018 - https://github.com/blender 7
  35. Kind Signatures Just as you can write type signatures y

    :: String -> IO () y = putStrLn You can write kind signatures data List a = Cons a (List a) | Nil {-# LANGUAGE KindSignatures #-} data List (a :: *) = Cons a (List a) | Nil © Tommaso Piazza, 2018 - https://github.com/blender 8
  36. HOFs Higher order functions take functions are paramters map ::

    (a -> b) -> [a] -> [b] © Tommaso Piazza, 2018 - https://github.com/blender 9
  37. HKTs Higher kinded types take type constuctors of kind *

    -> * as parameters {-# LANGUAGE KindSignatures #-} data NonEmpty (f :: * -> *) (a :: *) = MkNonEmpty { head :: a, tail :: f a } type NonEmptyList = NonEmpty [] let nonEmptyListOfInts = MkNonEmpty 1 [] :: NonEmptyList Int © Tommaso Piazza, 2018 - https://github.com/blender 10
  38. Not everything is a ⭐ © Tommaso Piazza, 2018 -

    https://github.com/blender 11
  39. Not everything is a ⭐ — :k Show © Tommaso

    Piazza, 2018 - https://github.com/blender 11
  40. Not everything is a ⭐ — :k Show — Show

    :: * -> Constraint © Tommaso Piazza, 2018 - https://github.com/blender 11
  41. Not everything is a ⭐ — :k Show — Show

    :: * -> Constraint — :k Functor © Tommaso Piazza, 2018 - https://github.com/blender 11
  42. Not everything is a ⭐ — :k Show — Show

    :: * -> Constraint — :k Functor — Functor :: (* -> *) -> Constraint © Tommaso Piazza, 2018 - https://github.com/blender 11
  43. Not everything is a ⭐ — :k Show — Show

    :: * -> Constraint — :k Functor — Functor :: (* -> *) -> Constraint — EverythingOnThisSide m => m IsAConstraint © Tommaso Piazza, 2018 - https://github.com/blender 11
  44. Constraints ! Use the Constraint kind by enabling {-# LANGUAGE

    ConstraintKinds #-} © Tommaso Piazza, 2018 - https://github.com/blender 12
  45. Using Constraints Data.Set has no Functor instance class Functor (f

    :: * -> *) where fmap :: (a -> b) -> f a -> f b Data.Set.map :: Ord b => (a -> b) -> Set a -> Set b -- *___ ▾ ___* -- ! © Tommaso Piazza, 2018 - https://github.com/blender 13
  46. Police Data.Set.map :: Ord b => (a -> b) ->

    Set a -> Set b -- *___ ▾ ___* * ▾ * * ▾ * -- ! f f © Tommaso Piazza, 2018 - https://github.com/blender 14
  47. Police Data.Set.map :: Ord b => (a -> b) ->

    Set a -> Set b -- *___ ▾ ___* * ▾ * * ▾ * -- ! f f class GFunctor ! (f :: * -> *) where fmap :: ! b => (a -> b) -> f a -> f b © Tommaso Piazza, 2018 - https://github.com/blender 15
  48. Police Data.Set.map :: Ord b => (a -> b) ->

    Set a -> Set b -- *___ ▾ ___* * ▾ * * ▾ * -- ! f f class GFunctor ! (f :: * -> *) where fmap :: ! b => (a -> b) -> f a -> f b class GFunctor (c :: * -> Constraint) (f :: * -> *) | f -> c where gfmap :: c b => (a -> b) -> (f a -> f b) © Tommaso Piazza, 2018 - https://github.com/blender 16
  49. !"# {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE KindSignatures #-} {-#

    LANGUAGE FunctionalDependencies #-} import Data.Kind (Constraint) import qualified Data.Set as Set import qualified Data.List as List class GFunctor (c :: * -> Constraint) (f :: * -> *) | f -> c where gfmap :: c b => (a -> b) -> (f a -> f b) instance GFunctor Ord Set.Set where gfmap = Set.map © Tommaso Piazza, 2018 - https://github.com/blender 17
  50. No ! no problem {-# LANGUAGE FlexibleInstances #-} class EmptyConstraint

    a instance EmptyConstraint a © Tommaso Piazza, 2018 - https://github.com/blender 18
  51. No ! no problem {-# LANGUAGE FlexibleInstances #-} class EmptyConstraint

    a instance EmptyConstraint a instance GFunctor EmptyConstraint [] where gfmap = List.map © Tommaso Piazza, 2018 - https://github.com/blender 19
  52. Promotions A data type like data ConnectionStatus = Open |

    Closed © Tommaso Piazza, 2018 - https://github.com/blender 20
  53. Promotions A data type like data ConnectionStatus = Open |

    Closed Can be promoted to a kind {-# LANGUAGE DataKinds #-} data ConnectionStatus = Open | Closed © Tommaso Piazza, 2018 - https://github.com/blender 21
  54. DataKinds © Tommaso Piazza, 2018 - https://github.com/blender 22

  55. DataKinds {-# LANGUAGE DataKinds #-} Creates a kind ConnectionStatus and

    two types 'Open and 'Closed © Tommaso Piazza, 2018 - https://github.com/blender 23
  56. DataKinds {-# LANGUAGE DataKinds #-} Creates a kind ConnectionStatus and

    two types 'Open and 'Closed — :t Open © Tommaso Piazza, 2018 - https://github.com/blender 23
  57. DataKinds {-# LANGUAGE DataKinds #-} Creates a kind ConnectionStatus and

    two types 'Open and 'Closed — :t Open — Open :: ConnectionStatus © Tommaso Piazza, 2018 - https://github.com/blender 23
  58. DataKinds {-# LANGUAGE DataKinds #-} Creates a kind ConnectionStatus and

    two types 'Open and 'Closed — :t Open — Open :: ConnectionStatus — :k Open (or :k 'Open ) © Tommaso Piazza, 2018 - https://github.com/blender 23
  59. DataKinds {-# LANGUAGE DataKinds #-} Creates a kind ConnectionStatus and

    two types 'Open and 'Closed — :t Open — Open :: ConnectionStatus — :k Open (or :k 'Open ) — Open :: ConnectionStatus © Tommaso Piazza, 2018 - https://github.com/blender 23
  60. Type level connections data Connection (s :: ConnectionStatus) = MkConnection

    { connectionId :: String } open :: IO (Connection Open) open = return $ MkConnection "someId" close :: Connection Open -> IO (Connection Closed) close (MkConnection c) = return $ MkConnection (c ++ " is now closed") © Tommaso Piazza, 2018 - https://github.com/blender 24
  61. Strings as types Kind Symbol fro GHC.TypeList newtype Money (currency

    :: Symbol) = Money Rational fivePence :: Money "GBP" fivePence = Money (5 % 100) © Tommaso Piazza, 2018 - https://github.com/blender 25
  62. Strings as types Kind Symbol newtype Money (currency :: Symbol)

    = Money Rational fivePence :: Money "GBP" fivePence = Money (5 % 100) twoEuros :: Money "EUR" twoEuros = Money 2 add :: Money c -> Money c -> Money c add (Money x) (Money y) = Money (x + y) add fivePence fivePence Money (1 % 10) add fivePence twoEuros <interactive>:8:15: error: • Couldn't match type ‘"EUR"’ with ‘"GBP"’ © Tommaso Piazza, 2018 - https://github.com/blender 26
  63. 1,2,3... as types Kind Nat {-# LANGUAGE KindSignatures, DataKinds #-}

    import GHC.TypeLits (Symbol, Nat) newtype Discrete (currency :: Symbol) (scale :: (Nat, Nat)) = Discrete Integer oneDollar :: Discrete "USD" '(1, 1) oneDollar = Discrete 1 oneDollarThirtyCents :: Discrete "USD" '(100, 1) oneDollarThirtyCents = Discrete 130 © Tommaso Piazza, 2018 - https://github.com/blender 27
  64. Be Kind Thanks! https://diogocastro.com/blog/2018/10/17/haskells-kind- system-a-primer © Tommaso Piazza, 2018 -

    https://github.com/blender 28
  65. I need help! https://github.com/blender/Rome — Writte in Haskell — Used

    by Mozilla and others — Tons of room for improvement © Tommaso Piazza, 2018 - https://github.com/blender 29