Stateful Programming in Idris Edwin Brady ( ecb10@st-andrews.ac.uk ) - - PowerPoint PPT Presentation

stateful programming in idris
SMART_READER_LITE
LIVE PREVIEW

Stateful Programming in Idris Edwin Brady ( ecb10@st-andrews.ac.uk ) - - PowerPoint PPT Presentation

Stateful Programming in Idris Edwin Brady ( ecb10@st-andrews.ac.uk ) University of St Andrews, Scotland, UK @edwinbrady Dagstuhl, 30th January 2017 1 / 22 Idris is a pure functional language with dependent types . Some goals: Reduce the cost of


slide-1
SLIDE 1

Stateful Programming in Idris

Edwin Brady (ecb10@st-andrews.ac.uk) University of St Andrews, Scotland, UK @edwinbrady Dagstuhl, 30th January 2017

1 / 22

slide-2
SLIDE 2

Idris is a pure functional language with dependent types. Some goals: Reduce the cost of writing correct software Be accessible to software developers and practitioners In this talk: Writing precise APIs with State Example: Sockets and Concurrency

2 / 22

slide-3
SLIDE 3

Socket States

3 / 22

slide-4
SLIDE 4

Socket Programming (in C)

Creating a server int socket(int domain, int type, int protocol); int bind(int socket, const struct sockaddr *address, socklen_t address_len); int listen(int socket, int backlog); int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len); int connect(int socket, struct sockaddr *address, socklen_t address_len) /* ... */

4 / 22

slide-5
SLIDE 5

Socket Programming (in C)

Which int is which? (Sockets) int socket(int domain, int type, int protocol); int bind(int socket, const struct sockaddr *address, socklen_t address_len); int listen(int socket, int backlog); int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len); int connect(int socket, struct sockaddr *address, socklen_t address_len) /* ... */

5 / 22

slide-6
SLIDE 6

Socket Programming (in C)

Which int is which? (Errors) int socket(int domain, int type, int protocol); int bind(int socket, const struct sockaddr *address, socklen_t address_len); int listen(int socket, int backlog); int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len); int connect(int socket, struct sockaddr *address, socklen_t address_len) /* ... */

6 / 22

slide-7
SLIDE 7

Socket Programming (in Haskell)

Creating a server socket :: Family -> SocketType -> ProtocolNumber -> IO Socket bind :: Socket -> SockAddr -> IO () listen :: Socket -> Int -> IO () accept :: Socket -> IO (Socket, SockAddr) connect :: Socket -> SockAddr -> IO ()

7 / 22

slide-8
SLIDE 8

Towards better APIs

Challenge: How can we write a descriptive API for sockets? Wishlist:

8 / 22

slide-9
SLIDE 9

Towards better APIs

Challenge: How can we write a descriptive API for sockets? Wishlist: Capture the states of the socket

8 / 22

slide-10
SLIDE 10

Towards better APIs

Challenge: How can we write a descriptive API for sockets? Wishlist: Capture the states of the socket Describe when operations are valid (i.e. preconditions)

8 / 22

slide-11
SLIDE 11

Towards better APIs

Challenge: How can we write a descriptive API for sockets? Wishlist: Capture the states of the socket Describe when operations are valid (i.e. preconditions) Describe how operations affect the environment (i.e. postconditions)

8 / 22

slide-12
SLIDE 12

Towards better APIs

Challenge: How can we write a descriptive API for sockets? Wishlist: Capture the states of the socket Describe when operations are valid (i.e. preconditions) Describe how operations affect the environment (i.e. postconditions) Interoperate with other stateful APIs

8 / 22

slide-13
SLIDE 13

Towards better APIs

Challenge: How can we write a descriptive API for sockets? Wishlist: Capture the states of the socket Describe when operations are valid (i.e. preconditions) Describe how operations affect the environment (i.e. postconditions) Interoperate with other stateful APIs Remain Readable

8 / 22

slide-14
SLIDE 14

Towards better APIs

Challenge: How can we write a descriptive API for sockets? Wishlist: Capture the states of the socket Describe when operations are valid (i.e. preconditions) Describe how operations affect the environment (i.e. postconditions) Interoperate with other stateful APIs Remain Readable Lead to helpful error messages

8 / 22

slide-15
SLIDE 15

Towards better APIs

Challenge: How can we write a descriptive API for sockets? Wishlist: Capture the states of the socket Describe when operations are valid (i.e. preconditions) Describe how operations affect the environment (i.e. postconditions) Interoperate with other stateful APIs Remain Readable Lead to helpful error messages Inspiration: Separation logic, Ynot, Indexed Monads, Linear Types . . .

8 / 22

slide-16
SLIDE 16

Example state machine: Doors

9 / 22

slide-17
SLIDE 17

State in Idris: ST

The type of stateful programs ST : (m : Type -> Type)

  • - Underlying monad
  • > (ty : Type)
  • - Result type
  • > List (Action ty)
  • - State transitions
  • - may depend on the result
  • > Type

10 / 22

slide-18
SLIDE 18

State in Idris: ST Example

A Door Program doorProg : Door m => ST m () [] doorProg = do d <- newDoor ringBell d OK <- doorOpen d | Jammed => delete d doorClose d delete d

11 / 22

slide-19
SLIDE 19

State in Idris: ST Example

Ringing the bell ringBell : (d : Var) -> ST m () [d ::: DoorType DoorClosed]

12 / 22

slide-20
SLIDE 20

State in Idris: ST Example

Ringing the bell ringBell : (d : Var) -> ST m () [d ::: DoorType DoorClosed] Closing a door doorClose : (d : Var) -> ST m () [d ::: DoorType DoorOpen :-> DoorType DoorClosed]

12 / 22

slide-21
SLIDE 21

State in Idris: ST Example

Opening a door (almost. . . ) doorOpen : (d : Var) -> ST m () [d ::: DoorType DoorClosed :-> DoorType DoorOpen]

13 / 22

slide-22
SLIDE 22

State in Idris: ST Example

Opening a door (with possible failure) data Result = OK | Jammed doorOpen : (d : Var) -> ST m Result [d ::: DoorType DoorClosed :-> (\res => DoorType (case res of Jammed => DoorClosed OK => DoorOpen))]

14 / 22

slide-23
SLIDE 23

State in Idris: ST Example

Creating a door newDoor : ST m Var [Add (\d => [d ::: DoorType DoorClosed])]

15 / 22

slide-24
SLIDE 24

State in Idris: ST Example

General idea: Define interfaces (closely related to type classes) for

  • perations in ST:

Abstract away underlying resource types (DoorType here) Implement interface for different contexts Use only needed interfaces

16 / 22

slide-25
SLIDE 25

State in Idris: ST Example

General idea: Define interfaces (closely related to type classes) for

  • perations in ST:

Abstract away underlying resource types (DoorType here) Implement interface for different contexts Use only needed interfaces The Door Interface interface Door (m : Type -> Type) where DoorType : DoorState -> Type newDoor : ... ringBell : ... doorOpen : ... doorClose : ...

16 / 22

slide-26
SLIDE 26

State in Idris: ST Example

A Door Program, with IO doorProg : (ConsoleIO m, Door m) => ST m () [] doorProg = do d <- newDoor ringBell d OK <- doorOpen d | Jammed => delete d lift (putStrLn "The Door is Open") doorClose d delete d

17 / 22

slide-27
SLIDE 27

Demonstration: Networking and Concurrency

18 / 22

slide-28
SLIDE 28

Internal details: STrans

The type of stateful programs STrans : (m : Type -> Type) -- Underlying monad

  • > (ty : Type)
  • - Result type
  • > Context
  • - Input states
  • > (ty -> Context) -- Output states
  • - may depend on the result
  • > Type

19 / 22

slide-29
SLIDE 29

Internal details: STrans

Reading and writing state get : (lbl : Var) -> {auto prf : InState lbl ty ctxt} -> STrans m ty ctxt (const ctxt) put : (lbl : Var) -> {auto prf : InState lbl ty ctxt} -> (val : ty’) -> STrans m () ctxt (const (updateCtxt ctxt prf ty’))

20 / 22

slide-30
SLIDE 30

Internal details: STrans

Returning a value pure : (result : val) -> STrans m val (out_fn result) out_fn

21 / 22

slide-31
SLIDE 31

https://www.tinyurl.com/typedd

22 / 22