$30 off During Our Annual Pro Sale. View Details »

Tic Tac Type: Dependent Types with Idris

Tic Tac Type: Dependent Types with Idris

Functional programming provides a fundamental basis for reasoning about our programs and building out principled abstractions. However, it is not enough on its own and we also rely on other programming tools to aid in constructing programs correctly and efficiently. An advanced example of such a tool is dependent types; that is, types that depend on values. Dependent types can be used to provide strong guarantees about a program's behaviour that are difficult or impossible to express with traditional type-systems.

Dependent types are gaining traction in mainstream FP languages such as Haskell (via language extensions) and Scala (via path-dependent sub-typing), but disappointingly, they are still less accessible to everyday programming than they can and should be. To help address this problem, Idris is a new programming language built from the ground up with the explicit goal of having better support for dependent types (as well as a number of other useful tools such as totality checking and tactic based theorem proving).

This talk will step through an end-to-end example in Idris, from fundamentals like building type-safe APIs, and performing IO through to building user interfaces. By the end of the talk we will have identified the strengths of this programming model, the practicalities of using them in Idris (in contrast to Scala and Haskell) and produced a battle-hardened, multi-player, tic-tac-toe game ready for production.

Mark Hibberd

May 09, 2014
Tweet

More Decks by Mark Hibberd

Other Decks in Programming

Transcript

  1. Tic
    @markhibberd
    Type
    Tac

    View Slide

  2. View Slide

  3. Data is validated with respect to other data
    !
    If types are to capture valid data precisely,
    we must let them depend on terms”
    - Conor McBride, Winging It

    View Slide

  4. View Slide

  5. IDRIS
    a primer

    View Slide

  6. haskell like syntax

    View Slide

  7. but…
    types and values co-exist in the
    same term language

    View Slide

  8. idris
    haskell
    !
    1 infixr 7 :.
    2
    3 data List a
    4 = Nil
    5 | a :. List a
    6
    7 headOr :: a -> List a -> a
    8 headOr x Nil = x
    9 headOr _ (h :. _) = h
    10
    11 type String =
    12 List Char
    1 infixr 7 :.
    2
    3 data List a
    4 = Nil
    5 | (:.) a (List a)
    6
    7 headOr : a -> List a -> a
    8 headOr x Nil = x
    9 headOr _ (h :. _) = h
    10
    11 String : Type
    12 String = List Char

    View Slide

  9. idris
    haskell
    !
    1 infixr 7 :.
    2
    3 data List a
    4 = Nil
    5 | a :. List a
    6
    7 headOr :: a -> List a -> a
    8 headOr x Nil = x
    9 headOr _ (h :. _) = h
    10
    11 type String =
    12 List Char
    1 infixr 7 :.
    2
    3 data List a
    4 = Nil
    5 | (:.) a (List a)
    6
    7 headOr : {a: Type} -> (x: a)
    -> (xs: List a) -> a
    8 headOr {a} x Nil = x
    9 headOr {a} _ (h :. _) = h
    10
    11 String : Type
    12 String = List Char

    View Slide

  10. idris
    haskell
    !
    1 data Nat
    2 = Z
    3 | S Nat
    !
    1 data Nat
    2 = Z
    3 | S Nat

    View Slide

  11. idris
    haskell
    !
    1 {-# LANGUAGE GADTs #-}
    2
    3 data Nat where
    4 Z :: Nat
    5 S :: Nat -> Nat
    !
    1 data Nat : Type where
    2 Z : Nat
    3 S : Nat -> Nat
    !
    !

    View Slide

  12. idris
    haskell
    !
    1 {-# LANGUAGE GADTs #-}
    2 {-# LANGUAGE KindSignatures #-}
    3
    4 data Nat :: * where
    5 Z :: Nat
    6 S :: Nat -> Nat
    !
    1 data Nat : Type where
    2 Z : Nat
    3 S : Nat -> Nat
    !
    !
    !

    View Slide

  13. idris
    haskell
    1 {-# LANGUAGE GADTs #-}
    2 {-# LANGUAGE KindSignatures #-}
    3
    4 data Z
    5 data S a = S a
    6
    7 data Nat a :: * -> * where
    8 Zero :: Nat Z
    9 Succ :: Nat n -> Nat (S n)
    10
    11 data Fin n :: * -> * where
    12 FZero :: Nat n -> Fin (S n)
    13 FSucc :: Nat n -> Fin n
    14 -> Fin (S n)
    !
    1 data Nat : Type where
    2 Z : Nat
    3 S : Nat -> Nat
    4
    5 data Fin : Nat -> Type where
    6 fZ : Fin (S k)
    7 fS : Fin k -> Fin (S k)
    !
    !
    !
    !
    !
    !
    !

    View Slide

  14. idris
    haskell
    !
    1 {-# LANGUAGE GADTs #-}
    2 {-# LANGUAGE DataKinds #-}
    3 {-# LANGUAGE KindSignatures #-}
    4
    5 data Nat :: * where
    6 Z :: Nat
    7 S :: Nat -> Nat
    8
    9 data Fin :: Nat -> * where
    10 FZ :: Fin Z
    11 FS :: Fin n -> Fin (S n)
    !
    1 data Nat : Type where
    2 Z : Nat
    3 S : Nat -> Nat
    4
    5 data Fin : Nat -> Type where
    6 fZ : Fin (S k)
    7 fS : Fin k -> Fin (S k)
    !
    !
    !
    !

    View Slide

  15. “Stick a number in my type. What is that?”
    - Manuel Chakravarty

    View Slide

  16. !
    1 data Vect : Nat -> Type -> Type where
    2 Nil : Vect Z a
    3 (::) : (x : a) -> (xs : Vect n a) -> Vect (S n) a
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  17. !
    1 data Vect : Nat -> Type -> Type where
    2 Nil : Vect Z a
    3 (::) : (x : a) -> (xs : Vect n a) -> Vect (S n) a
    4
    5 v2 : Vect 2 String
    6 v2 = "hello" :: "idris" :: Nil
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  18. 1 data Vect : Nat -> Type -> Type where
    2 Nil : Vect Z a
    3 (::) : (x : a) -> (xs : Vect n a) -> Vect (S n) a
    4
    5 v2 : Vect 2 String
    6 v2 = "hello" :: "idris" :: Nil
    7
    8 v3 : Vect ?len String
    9 v3 = "tic" :: "tac" :: "type" :: Nil
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  19. 1 data Vect : Nat -> Type -> Type where
    2 Nil : Vect Z a
    3 (::) : (x : a) -> (xs : Vect n a) -> Vect (S n) a
    4
    5 v2 : Vect 2 String
    6 v2 = "hello" :: "idris" :: Nil
    7
    8 v3 : Vect ?len String
    9 v3 = "tic" :: "tac" :: "type" :: Nil
    10
    11 len = proof search
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  20. !
    1 data Vect : Nat -> Type -> Type where
    2 Nil : Vect Z a
    3 (::) : (x : a) -> (xs : Vect n a) -> Vect (S n) a
    4
    5 index : Fin n -> Vect n a -> a
    6 index fZ (x::xs) = x
    7 index (fS k) (x::xs) = index k xs
    8 index fZ [] impossible
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  21. 1 (++) : Vect n a -> Vect m a -> Vect (n + m) a
    2 (++) Nil m = m
    3 (++) (h :: t) m = h :: (t ++ m)
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  22. 1 (++) : Vect n a -> Vect m a -> Vect (n + m) a
    2 (++) Nil m = m
    3 (++) (h :: t) m = h :: (t ++ m)
    4
    5 filter : (a -> Bool) -> Vect n a -> (p ** Vect p a)
    6 filter p [] = ( _ ** [] )
    7 filter p (x::xs) with (filter' p xs)
    8 | (n ** tail) =
    9 if p x then
    10 ((S n) ** x::tail)
    11 else
    12 (n ** tail)
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  23. what did I just see?

    View Slide

  24. dependent product types
    aka ∏ types

    View Slide

  25. dependent sum types
    aka Σ types

    View Slide

  26. Curry–Howard correspondence

    View Slide

  27. (Intuitionistic) Logic Programming
    FALSE ⊥
    TRUE ()
    Disjunction (or) Sum Types
    Conjunction (and) Product Types
    Implication Function Types

    View Slide

  28. (Predicate) Logic Programming
    FALSE ⊥
    TRUE ()
    Disjunction (or) Sum Types
    Conjunction (and) Product Types
    Implication Function Types
    Existential Quantification (exists.) Σ Types
    Universal Quantification (forall.) ∏ Types

    View Slide

  29. So how do we go about
    constructing programs?

    View Slide

  30. Start With Value Level Primitives

    View Slide

  31. 1 data Player = X | O
    2 data Cell = Occupied Player | Unoccupied
    3
    4 instance Show Player where {...}
    5 instance Eq Player where {...}
    6 instance Show Cell where {...}
    7 instance Eq Cell where {…}
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  32. north-east
    north-west north
    center east
    west
    south-east
    south-west south

    View Slide

  33. 1 Position : Type
    2 Position = Fin 9
    3
    4 nw : Position
    5 nw = 0
    6 {...}
    7 se : Position
    8 se = 8
    9
    10 parse : String -> Maybe Position
    11 parse "nw" = Just nw
    12 parse "n" = Just n
    13 parse "ne" = Just ne
    14 parse "e" = Just e
    15 parse "c" = Just c
    16 parse "w" = Just w
    17 parse "sw" = Just sw
    18 parse "s" = Just s
    19 parse "se" = Just se
    20 parse _ = Nothing

    View Slide

  34. 1 data Board =
    2 B (Vect 9 Cell)
    3
    4 instance Eq Board where {...}
    5 instance Show Board where {...}
    6
    7 -- How many positions are occupied ?
    8 occupied : Board -> Nat
    9
    10 -- Who's turn is it?
    11 turn : Board -> Player
    12
    13 -- Is this position free?
    14 free : Position -> Board -> Bool
    15
    16 -- Is there a winner on the board?
    17 winner : Board -> Maybe Player
    18
    19 -- Is this a valid board?
    20 isValidBoard : Board -> Bool

    View Slide

  35. Types and Proofs

    View Slide

  36. !
    1 data so : Bool -> Type where
    2 oh : so True
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  37. !
    1 data so : Bool -> Type where
    2 oh : so True
    3
    4 printIf3 : (n: Nat)
    5 -> {default oh prf : so (n == 3)}
    6 -> IO ()
    7 printIf3 _ =
    8 print "3s are good."
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  38. *> :x printIf3 3
    "3s are good."
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  39. *> :x printIf3 3
    "3s are good."
    !
    *> :x printIf3 3 { prf = oh }
    "3s are good.”
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  40. *> :x printIf3 3
    "3s are good."
    !
    *> :x printIf3 3 { prf = oh }
    "3s are good.”
    !
    *> :x printIf3 2
    (input):1:13:When elaborating argument prf to
    function Main.printIf3:
    Can't unify
    IsJust (Just x)
    with
    IsJust (fromInteger 2 == (fromInteger 3))
    !
    Specifically:
    Can't unify
    True
    with
    False
    !

    View Slide

  41. 1 natToFin : Nat -> (n : Nat) -> Maybe (Fin n)
    2 natToFin Z (S j) = Just fZ
    3 natToFin (S k) (S j) with (natToFin k j)
    4 | Just k' = Just (fS k')
    5 | Nothing = Nothing
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  42. 1 natToFin : Nat -> (n : Nat) -> Maybe (Fin n)
    2 natToFin Z (S j) = Just fZ
    3 natToFin (S k) (S j) with (natToFin k j)
    4 | Just k' = Just (fS k')
    5 | Nothing = Nothing
    6
    7 data IsJust : Maybe a -> Type where
    8 ItIsJust : IsJust {a} (Just x)
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  43. 1 natToFin : Nat -> (n : Nat) -> Maybe (Fin n)
    2 natToFin Z (S j) = Just fZ
    3 natToFin (S k) (S j) with (natToFin k j)
    4 | Just k' = Just (fS k')
    5 | Nothing = Nothing
    6
    7 data IsJust : Maybe a -> Type where
    8 ItIsJust : IsJust {a} (Just x)
    9
    10 fromNat : (x: Nat)
    11 -> {default ItIsJust
    12 prf : (IsJust (natToFin x n))}
    13 -> Fin n
    !
    !
    !
    !
    !
    !
    !

    View Slide

  44. 1 natToFin : Nat -> (n : Nat) -> Maybe (Fin n)
    2 natToFin Z (S j) = Just fZ
    3 natToFin (S k) (S j) with (natToFin k j)
    4 | Just k' = Just (fS k')
    5 | Nothing = Nothing
    6
    7 data IsJust : Maybe a -> Type where
    8 ItIsJust : IsJust {a} (Just x)
    9
    10 fromNat : (x: Nat)
    11 -> {default ItIsJust
    12 prf : (IsJust (natToFin x n))}
    13 -> Fin n
    14 fromNat {n} x {prf} with (natToFin x n)
    !
    !
    !
    !
    !

    View Slide

  45. 1 natToFin : Nat -> (n : Nat) -> Maybe (Fin n)
    2 natToFin Z (S j) = Just fZ
    3 natToFin (S k) (S j) with (natToFin k j)
    4 | Just k' = Just (fS k')
    5 | Nothing = Nothing
    6
    7 data IsJust : Maybe a -> Type where
    8 ItIsJust : IsJust {a} (Just x)
    9
    10 fromNat : (x: Nat)
    11 -> {default ItIsJust
    12 prf : (IsJust (natToFin x n))}
    13 -> Fin n
    14 fromNat {n} x {prf} with (natToFin x n)
    15 fromNat {n} x {prf = ItIsJust} | Just y = y
    !
    !
    !
    !
    !

    View Slide

  46. !
    1 *> fromNat 7
    2 Can't resolve type class Enum iType
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  47. !
    1 *> fromNat 7
    2 Can't resolve type class Enum iType
    3
    4 *FinProof> :t the
    5 Prelude.Basics.the : (a : Type) -> a -> a
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  48. !
    1 *> fromNat 7
    2 Can't resolve type class Enum iType
    3
    4 *FinProof> :t the
    5 Prelude.Basics.the : (a : Type) -> a -> a
    6
    7 *FinProof> the (Fin 10) (fromNat 7)
    8 fS (fS (fS (fS (fS (fS (fS fZ)))))) : Fin 10
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  49. !
    1 *> fromNat 7
    2 Can't resolve type class Enum iType
    3
    4 *FinProof> :t the
    5 Prelude.Basics.the : (a : Type) -> a -> a
    6
    7 *FinProof> the (Fin 10) (fromNat 7)
    8 fS (fS (fS (fS (fS (fS (fS fZ)))))) : Fin 10
    9
    10 *FinProof> the (Fin 10) (fromNat 10)
    11 (input):1:23:When elaborating argument prf
    12 Can't unify
    13 IsJust (Just x)
    14 with
    15 IsJust (natToFin 10 10)
    16
    17 Specifically:
    18 Can't unify
    19 Just x
    20 with
    21 Nothing

    View Slide

  50. 1 data ValidMove : Board -> Type where
    2 IsValidMove : Position -> Player
    3 -> (b : Board) -> ValidMove b
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  51. 1 data ValidMove : Board -> Type where
    2 IsValidMove : Position -> Player
    3 -> (b : Board) -> ValidMove b
    4
    5 tryValidMove : Position
    6 -> Player
    7 -> (b : Board)
    8 -> Maybe (ValidMove b)
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  52. 1 data ValidMove : Board -> Type where
    2 IsValidMove : Position -> Player
    3 -> (b : Board) -> ValidMove b
    4
    5 tryValidMove : Position
    6 -> Player
    7 -> (b : Board)
    8 -> Maybe (ValidMove b)
    9
    10 validMove : (pos : Position)
    11 -> (p : Player)
    12 -> (b : Board)
    13 -> {default ItIsJust
    14 prf : IsJust (tryValidMove pos p b)}
    15 -> ValidMove
    !
    !
    !
    !
    !

    View Slide

  53. 1 data ValidMove : Board -> Type where
    2 IsValidMove : Position -> Player
    3 -> (b : Board) -> ValidMove b
    4
    5 tryValidMove : Position
    6 -> Player
    7 -> (b : Board)
    8 -> Maybe (ValidMove b)
    9
    10 validMove : (pos : Position)
    11 -> (p : Player)
    12 -> (b : Board)
    13 -> {default ItIsJust
    14 prf : IsJust (tryValidMove pos p b)}
    15 -> ValidMove
    16 validMove pos p b {prf} with (tryValidMove pos p b)
    !
    !
    !
    !

    View Slide

  54. 1 data ValidMove : Board -> Type where
    2 IsValidMove : Position -> Player
    3 -> (b : Board) -> ValidMove b
    4
    5 tryValidMove : Position
    6 -> Player
    7 -> (b : Board)
    8 -> Maybe (ValidMove b)
    9
    10 validMove : (pos : Position)
    11 -> (p : Player)
    12 -> (b : Board)
    13 -> {default ItIsJust
    14 prf : IsJust (tryValidMove pos p b)}
    15 -> ValidMove
    16 validMove pos p b {prf} with (tryValidMove pos p b)
    17 validMove pos p b {prf = ItIsJust} | Just y = y
    !
    !
    !

    View Slide

  55. Break on Through to the Other Side

    View Slide

  56. 1 data Game : Board -> Type where
    2
    3 -- start a new game with an empty board
    4 start : Game empty
    5
    6 -- make a (guaranteed to be valid) move
    7 move' : {b : Board} -> (m : ValidMove b)
    8 -> Game b -> Game (runMove m)
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  57. !
    1 -- Make a valid move
    2 runMove : ValidMove board -> Board
    3 runMove (IsValidMove position player (B board)) =
    4 B $ replaceAt position (Occupied player) board
    5
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  58. !
    1 -- Make a valid move
    2 runMove : ValidMove board -> Board
    3 runMove (IsValidMove position player (B board)) =
    4 B $ replaceAt position (Occupied player) board
    5
    6 -- Make a valid move if you can prove it
    7 move : {b : Board}
    8 -> (pos : Position)
    9 -> (p : Player)
    10 -> (g : Game board)
    11 -> {default ItIsJust
    12 prf : (IsJust (tryValidMove pos p b))}
    13 -> Game (runMove $ validMove pos p b {prf})
    !
    !
    !
    !
    !
    !
    !

    View Slide

  59. !
    1 -- Make a valid move
    2 runMove : ValidMove board -> Board
    3 runMove (IsValidMove position player (B board)) =
    4 B $ replaceAt position (Occupied player) board
    5
    6 -- Make a valid move if you can prove it
    7 move : {b : Board}
    8 -> (pos : Position)
    9 -> (p : Player)
    10 -> (g : Game board)
    11 -> {default ItIsJust
    12 prf : (IsJust (tryValidMove pos p b))}
    13 -> Game (runMove $ validMove pos p b {prf})
    14 move {b} pos p g {prf} =
    15 move' (validMove pos p b {prf}) game
    !
    !
    !
    !
    !

    View Slide

  60. 1 data Prev : Game b -> Type where
    2 HasPrev : {bb : Board}
    3 -> {m : ValidMove bb}
    4 -> {g : Game bb}
    5 -> Prev (move' m g)
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  61. 1 data Prev : Game b -> Type where
    2 HasPrev : {bb : Board}
    3 -> {m : ValidMove bb}
    4 -> {g : Game bb}
    5 -> Prev (move' m g)
    6
    7 -- What was the previous board?
    8 previousBoard : (gg : Game b)
    9 -> {default HasPrev prf : (Prev gg)}
    10 -> Board
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  62. 1 data Prev : Game b -> Type where
    2 HasPrev : {bb : Board}
    3 -> {m : ValidMove bb}
    4 -> {g : Game bb}
    5 -> Prev (move' m g)
    6
    7 -- What was the previous board?
    8 previousBoard : (gg : Game b)
    9 -> {default HasPrev prf : (Prev gg)}
    10 -> Board
    11 previousBoard (move' {b} m g) {prf = HasPrev} = b
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  63. 1 data Prev : Game b -> Type where
    2 HasPrev : {bb : Board}
    3 -> {m : ValidMove bb}
    4 -> {g : Game bb}
    5 -> Prev (move' m g)
    6
    7 -- What was the previous board?
    8 previousBoard : (gg : Game b)
    9 -> {default HasPrev prf : (Prev gg)}
    10 -> Board
    11 previousBoard (move' {b} m g) {prf = HasPrev} = b
    12
    13 -- Take back the last move?
    14 takeBack : (gg : Game b)
    15 -> {default HasPrev prf : (Prev gg)}
    16 -> Game (previousBoard gg {prf})
    !
    !
    !
    !

    View Slide

  64. 1 data Prev : Game b -> Type where
    2 HasPrev : {bb : Board}
    3 -> {m : ValidMove bb}
    4 -> {g : Game bb}
    5 -> Prev (move' m g)
    6
    7 -- What was the previous board?
    8 previousBoard : (gg : Game b)
    9 -> {default HasPrev prf : (Prev gg)}
    10 -> Board
    11 previousBoard (move' {b} m g) {prf = HasPrev} = b
    12
    13 -- Take back the last move?
    14 takeBack : (gg : Game b)
    15 -> {default HasPrev prf : (Prev gg)}
    16 -> Game (previousBoard gg {prf})
    17 takeBack (move' {b} m g) {prf = HasPrev} = g
    !
    !
    !

    View Slide

  65. 1 game0 : ?t1
    2 game0 = start
    3 t1 = proof search
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  66. 1 game0 : ?t1
    2 game0 = start
    3 t1 = proof search
    4
    5 --game0x : ?t2
    6 --game0x = takeBack game0
    7 --t3 = proof search
    8
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  67. 1 game0 : ?t1
    2 game0 = start
    3 t1 = proof search
    4
    5 --game0x : ?t2
    6 --game0x = takeBack game0
    7 --t3 = proof search
    8
    9 game1 : ?t3
    10 game1 = move ne X game0
    11 t3 = proof search
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  68. 1 game0 : ?t1
    2 game0 = start
    3 t1 = proof search
    4
    5 --game0x : ?t2
    6 --game0x = takeBack game0
    7 --t3 = proof search
    8
    9 game1 : ?t3
    10 game1 = move ne X game0
    11 t3 = proof search
    12
    13 --game1x : ?t4
    14 --game1x = move ne O game1
    15 --t4 = proof search
    !
    !
    !
    !
    !

    View Slide

  69. 1 game0 : ?t1
    2 game0 = start
    3 t1 = proof search
    4
    5 --game0x : ?t2
    6 --game0x = takeBack game0
    7 --t3 = proof search
    8
    9 game1 : ?t3
    10 game1 = move ne X game0
    11 t3 = proof search
    12
    13 --game1x : ?t4
    14 --game1x = move ne O game1
    15 --t4 = proof search
    16
    17 game2 : ?t5
    18 game2 = move sw O game1
    19 t5 = proof search
    !

    View Slide

  70. Existentials for Free

    View Slide

  71. 1 data TicTacToeState =
    2 InPlay | Done
    3
    4 toState : Board -> TicTacToeState
    5 toState b =
    6 case (winner b, complete b) of
    7 (Just p, _) => Done
    8 (Nothing, True) => Done
    9 (Nothing, False) => InPlay
    10
    11 data TicTacToe : TicTacToeState -> Type where
    12 T : (Game b) -> TicTacToe (toState b)
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  72. Effects

    View Slide

  73. !
    1 Eff : (m : Type -> Type)
    2 -> (x : Type)
    3 -> List EFFECT
    4 -> (x -> List EFFECT)
    5 -> Type
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  74. !
    1 Eff : (m : Type -> Type)
    2 -> (x : Type)
    3 -> List EFFECT
    4 -> (x -> List EFFECT)
    5 -> Type
    6
    7
    8 STATE : Type -> EFFECT
    9 EXCEPTION : Type -> EFFECT
    10 FILEIO : Type -> EFFECT
    11 STDIO : EFFECT
    12 RND : EFFECT
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  75. 1 data TicTacToeRules : Effect where
    2 Move :
    3 (position : Position)
    4 -> (player : Player)
    5 -> { TicTacToe st ==> {st'} (TicTacToe st') }
    6 TicTacToeRules TicTacToeState
    7
    8 Get : { g } TicTacToeRules g
    9
    10 GetBoard : { TicTacToe st } TicTacToeRules Board
    11
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  76. 1 data TicTacToeRules : Effect where
    2 Move :
    3 (position : Position)
    4 -> (player : Player)
    5 -> { TicTacToe st ==> {st'} (TicTacToe st') }
    6 TicTacToeRules TicTacToeState
    7
    8 Get : { g } TicTacToeRules g
    9
    10 GetBoard : { TicTacToe st } TicTacToeRules Board
    11
    12 TICTACTOE : TicTacToeState -> EFFECT
    13 TICTACTOE s = MkEff (TicTacToe s) TicTacToeRules
    !
    !
    !
    !
    !
    !
    !

    View Slide

  77. 1 using (m : Type -> Type)
    2 instance Handler TicTacToeRules m where
    3 handle (T game) (Move position player) k
    4 handle t Get k
    5 handle (T game) GetBoard k
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  78. 1 using (m : Type -> Type)
    2 instance Handler TicTacToeRules m where
    3 handle (T game) (Move position player) k =
    4 let b = toBoard game in
    5 case tryValidMove position player b of
    6 Just m' =>
    7 let updated = move' m' game in
    8 k (toState . toBoard $ updated) (T updated)
    9 Nothing =>
    10 k (toState . toBoard $ game) (T game)
    11
    12 handle t Get k =
    13 k t t
    14
    15 handle (T game) GetBoard k =
    16 k (toBoard game) (T game)
    !
    !
    !
    !

    View Slide

  79. 1 game : { [TICTACTOE InPlay, STDIO] ==>
    2 [TICTACTOE Done, STDIO] } Eff IO ()
    3 game = do
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  80. 1 game : { [TICTACTOE InPlay, STDIO] ==>
    2 [TICTACTOE Done, STDIO] } Eff IO ()
    3 game = do
    4 let current = !GetBoard
    5 let player = turn current
    6 let _ = !(printState current player)
    7 let input = !getStr
    8 case parse (trim input) of
    9 Nothing => '
    10 do putStrLn $ "Invalid move: " ++ input
    11 pure !game
    12 Just position =>
    13 do InPlay <- Move position player
    14 | Done => putStrLn "Done"
    15 game
    !
    !
    !
    !
    !

    View Slide

  81. Constraints are Context Dependent

    View Slide

  82. !
    1 data CurrentGame : Type where
    2 Current : (TicTacToe state) -> CurrentGame
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  83. !
    1 data CurrentGame : Type where
    2 Current : (TicTacToe state) -> CurrentGame
    3
    4 receive' : { [STDIO,
    5 STATE CurrentGame,
    6 TCPSERVERCLIENT ClientConnected] ==>
    7 [STDIO,
    8 STATE CurrentGame,
    9 TCPSERVERCLIENT ()] } Eff IO ()
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  84. !
    1 data CurrentGame : Type where
    2 Current : (TicTacToe state) -> CurrentGame
    3
    4 receive' : { [STDIO,
    5 STATE CurrentGame,
    6 TCPSERVERCLIENT ClientConnected] ==>
    7 [STDIO,
    8 STATE CurrentGame,
    9 TCPSERVERCLIENT ()] } Eff IO ()
    10
    11 game : CurrentGame -> Game x
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  85. !
    1 data CurrentGame : Type where
    2 Current : (TicTacToe state) -> CurrentGame
    3
    4 receive' : { [STDIO,
    5 STATE CurrentGame,
    6 TCPSERVERCLIENT ClientConnected] ==>
    7 [STDIO,
    8 STATE CurrentGame,
    9 TCPSERVERCLIENT ()] } Eff IO ()
    10
    11 game : CurrentGame -> Game x —??????????
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  86. !
    1 data CurrentGame : Type where
    2 Current : (TicTacToe state) -> CurrentGame
    3
    4 receive' : { [STDIO,
    5 STATE CurrentGame,
    6 TCPSERVERCLIENT ClientConnected] ==>
    7 [STDIO,
    8 STATE CurrentGame,
    9 TCPSERVERCLIENT ()] } Eff IO ()
    10
    11 game : CurrentGame -> (x ** Game x)
    12 game (Current (T z)) =
    13 (toBoard z ** z)
    !
    !
    !
    !
    !
    !
    !

    View Slide

  87. !
    1 data CurrentGame : Type where
    2 Current : (TicTacToe state) -> CurrentGame
    3
    4 receive' : { [STDIO,
    5 STATE CurrentGame,
    6 TCPSERVERCLIENT ClientConnected] ==>
    7 [STDIO,
    8 STATE CurrentGame,
    9 TCPSERVERCLIENT ()] } Eff IO ()
    10
    11 game : CurrentGame -> (x ** Game x)
    !
    !
    !
    !
    !
    !
    !
    !
    !

    View Slide

  88. “the most popular and best
    established lightweight formal
    methods are type systems”
    - Benjamin Pierce, Types and Programming Languages

    View Slide

  89. Tic
    @markhibberd
    Type
    Tac

    View Slide