Slide 1

Slide 1 text

A NUMBER BY ANY OTHER NAME

Slide 2

Slide 2 text

JOËL QUENNEVILLE

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

MARS CLIMATE ORBITER

Slide 6

Slide 6 text

WHAT HAPPENED?

Slide 7

Slide 7 text

Root Cause: Failure to use metric units in the coding of a trajectory model.

Slide 8

Slide 8 text

[...] the navigation software algorithm therefore, underestimated the effect on the spacecraft trajectory by a factor of 4.45 [...]

Slide 9

Slide 9 text

An erroneous trajectory was computed using this incorrect data.

Slide 10

Slide 10 text

I'M NOT BUILDING SPACECRAFT

Slide 11

Slide 11 text

PLAYING FAST AND LOOSE WITH NUMBERS

Slide 12

Slide 12 text

3 KINDS OF MISTAKES 1. Argument order 2. Unit conversion 3. Invalid operation

Slide 13

Slide 13 text

ARGUMENT ORDER ERROR

Slide 14

Slide 14 text

ARGUMENT ORDER ERROR speed : Float -> Float -> Float speed distance time = distance / time

Slide 15

Slide 15 text

ARGUMENT ORDER ERROR distance = 10 time = 5 -- WHICH ONE? speed distance time speed time distance

Slide 16

Slide 16 text

HOW CAN WE MAKE FEWER OF THESE MISTAKES?

Slide 17

Slide 17 text

COMMUNICATION

Slide 18

Slide 18 text

CONFUSING Float -> Float -> Float

Slide 19

Slide 19 text

WHAT DO THESE NUMBERS REPRESENT?

Slide 20

Slide 20 text

FUNDAMENTALLY DIFFERENT QUANTITIES

Slide 21

Slide 21 text

WHAT ABOUT THIS Meter -> Second -> MeterPerSecond

Slide 22

Slide 22 text

TYPE ALIASES

Slide 23

Slide 23 text

PROVIDE ALTERNATE NAME FOR EXISTING TYPES

Slide 24

Slide 24 text

COMPILER CAN'T TELL THE DIFFERENCE Float -> Float -> Float -- SAME AS Meter -> Second -> MeterPerSecond

Slide 25

Slide 25 text

TYPE ALIASES ARE FOR HUMANS ONLY

Slide 26

Slide 26 text

[the Elm compiler] has my back when I make a dumb mistake. It brings joy into front-end programming. - Joël Quenneville

Slide 27

Slide 27 text

WHAT IF THE COMPILER COULD HELP US?

Slide 28

Slide 28 text

COMMUNICATION

Slide 29

Slide 29 text

CUSTOM TYPES type Meter = Meter Float type Second = Second Float type MetersPerSecond = MetersPerSecond Float

Slide 30

Slide 30 text

CAN'T DO MATH ON THESE

Slide 31

Slide 31 text

speed : Meter -> Second -> MetersPerSecond speed (Meter m) (Second s) = MetersPerSecond (m / s)

Slide 32

Slide 32 text

ARGUMENT ORDER ERROR - TYPED distance = Meter 10 time = Second 5 -- Wrong argument order myVal = speed time distance

Slide 33

Slide 33 text

The 1st argument to `speed` is not what I expect: 21| myVal = speed time distance ^^^^ This `time` value is a: Second But `speed` needs the 1st argument to be: Meter

Slide 34

Slide 34 text

3 KINDS OF MISTAKES 1. Argument order 2. Unit conversion 3. Invalid operation

Slide 35

Slide 35 text

UNIT CONVERSION ERROR

Slide 36

Slide 36 text

UNIT CONVERSION ERROR minutes = 40 hours = 2 total = minutes + hours -- RETURNS 42 -- SHOULD RETURN 160 OR 2.67

Slide 37

Slide 37 text

CAN THE COMPILER HELP?

Slide 38

Slide 38 text

COMMUNICATE

Slide 39

Slide 39 text

CREATE CUSTOM ADD FUNCTION? add : Minute -> Hour -> ???

Slide 40

Slide 40 text

COMBINATORIAL EXPLOSION add : Minute -> Hour -> ??? add : Minute -> Minute -> ??? add : Hour -> Hour -> ???

Slide 41

Slide 41 text

!

Slide 42

Slide 42 text

WHAT KIND OF QUANTITIES DO THESE NUMBERS REPRESENT?

Slide 43

Slide 43 text

DIFFERENT VARIATIONS OF THE SAME QUANTITY

Slide 44

Slide 44 text

SHARE A TYPE add : Time -> Time -> Time

Slide 45

Slide 45 text

OPAQUE TYPES

Slide 46

Slide 46 text

OPAQUE TYPES module Time exposing (Time) type Time = Time Float

Slide 47

Slide 47 text

OPAQUE TYPES module Time exposing (Time, fromMinutes) -- OTHER STUFF fromMinutes : Float -> Time fromMinutes mins = Time mins

Slide 48

Slide 48 text

OPAQUE TYPES module Time exposing (Time, fromMinutes, fromHours) -- OTHER STUFF fromHours : Float -> Time fromHours hrs = Time (hrs * 60)

Slide 49

Slide 49 text

OPAQUE TYPES module Time exposing (Time, fromMinutes, fromHours, add) -- OTHER STUFF add : Time -> Time -> Time add (Time t1) (Time t2) = Time (t1 + t2)

Slide 50

Slide 50 text

OPAQUE TYPES module Time exposing (Time, fromMinutes, fromHours, add) -- OTHER STUFF inHours : Time -> Float inHours (Time t) toFloat t / 60

Slide 51

Slide 51 text

minutes = Time.fromMinutes 40 hours = Time.fromHours 2 total = Time.add hours minutes -- RETURNS `Time 160`

Slide 52

Slide 52 text

UNIT CONVERSIONS HAPPEN AUTOMATICALLY

Slide 53

Slide 53 text

SINGLE POINT OF FAILURE

Slide 54

Slide 54 text

ELM 0.19 INTRODUCES Posix TYPE

Slide 55

Slide 55 text

MONEY

Slide 56

Slide 56 text

MONEY usd = 5 eur = 10 total = usd + eur -- RETURNS 15 -- SHOULD BE ??

Slide 57

Slide 57 text

WHAT KIND OF QUANTITIES DO THESE NUMBERS REPRESENT?

Slide 58

Slide 58 text

RULES 1. Can only add currencies of the same type 2. Can convert currencies of different types given a rate

Slide 59

Slide 59 text

TWO OPAQUE TYPES

Slide 60

Slide 60 text

module Usd exposing(Usd, fromCents, add, toEur) add : Usd -> Usd -> Usd toEur : Float -> Usd -> Eur -- MORE CODE

Slide 61

Slide 61 text

module Eur exposing (Eur, fromCents, add, toUsd) add : Eur -> Eur -> Eur toUsd : Float -> Eur -> Usd -- MORE CODE

Slide 62

Slide 62 text

SUCCESS? usd = Usd.fromCents 500 eur = Eur.fromCents 1000 total = eur |> Eur.toUsd 1.14 |> Usd.add usd -- RETURNS `Usd 1640`

Slide 63

Slide 63 text

NEW CURRENCY - JPY

Slide 64

Slide 64 text

Jpy.add Jpy.toUsd Jpy.toEur Eur.toJpy Usd.toJpy

Slide 65

Slide 65 text

COMBINATORIAL EXPLOSION

Slide 66

Slide 66 text

!

Slide 67

Slide 67 text

WE WANT 1. Implement adding once 2. Implement conversion once

Slide 68

Slide 68 text

RULES 1. Can only add currencies of the same type 2. Can convert currencies of different types given a rate

Slide 69

Slide 69 text

COMMUNICATE

Slide 70

Slide 70 text

add : Currency a -> Currency a -> Currency a convert : ConversionRate from to -> Currency from -> Currency to

Slide 71

Slide 71 text

PHANTOM TYPES

Slide 72

Slide 72 text

TWO THINGS ARE DIFFERENT WHILE SHARING AN IMPLEMENTATION

Slide 73

Slide 73 text

module Currency exposing (Currency, Usd, Eur, Jpy) type Usd = Usd type Eur = Eur type Jpy = Jpy type Currency a = Currency Float

Slide 74

Slide 74 text

module Currency exposing (Currency, Usd, Eur, Jpy, add) -- OTHER CODE add : Currency a -> Currency a -> Currency a add (Currency c1) (Currency c2) = Currency (c1 + c2)

Slide 75

Slide 75 text

usd : Currency Usd usd = Currency 500 eur : Currency Eur eur = Currency 1000 total = Currency.add usd eur

Slide 76

Slide 76 text

The 2nd argument to `add` is not what I expect: 29| add usd eur ^^^ This `eur` value is a: Currency Eur But `add` needs the 2nd argument to be: Currency Usd

Slide 77

Slide 77 text

CONSTRAINT ENFORCED!

Slide 78

Slide 78 text

CONVERSION - PHANTOM TYPE X 2 type ConversionRate from to = ConversionRate Float convert : ConversionRate from to -> Currency from -> Currency to convert (ConversionRate rate) (Currency c) = Currency (rate * c)

Slide 79

Slide 79 text

-- usd AND eur DEFINITIONS HIDDEN rate : ConversionRate Eur Usd rate = ConversionRate 1.12 total = eur |> Currency.convert rate |> Currency.add usd

Slide 80

Slide 80 text

GOING ALL THE WAY addDifferent : Currency a -> ConversionRate a b -> Currency b -> Currency b

Slide 81

Slide 81 text

3 KINDS OF MISTAKES 1. Argument order 2. Unit conversion 3. Invalid operation

Slide 82

Slide 82 text

INVALID OPERATION

Slide 83

Slide 83 text

MAKE NO SENSE IN YOUR DOMAIN

Slide 84

Slide 84 text

INVALID OPERATION total : Float -> Float -> Float total subTotal tax = subTotal * tax

Slide 85

Slide 85 text

total : Dollar -> Dollar -> DollarSquared total subTotal tax = subTotal |> Dollar.times tax

Slide 86

Slide 86 text

WHAT DOES A NUMBER REPRESENT

Slide 87

Slide 87 text

DON'T TRY TO IMPLEMENT EVERY MATH FUNCTION

Slide 88

Slide 88 text

No code has no bugs

Slide 89

Slide 89 text

UNITS GUIDE US ON WHAT CODE NOT TO WRITE

Slide 90

Slide 90 text

CASE STUDY: MIT SPRING

Slide 91

Slide 91 text

UNIX TIMESTAMPS

Slide 92

Slide 92 text

VIDEO TIMESTAMPS

Slide 93

Slide 93 text

VIDEO OFFSET

Slide 94

Slide 94 text

REFACTORING BY INTRODUCING A TYPE

Slide 95

Slide 95 text

toUnix : VideoEpoch -> VideoTime -> UnixTime

Slide 96

Slide 96 text

GRADUALLY

Slide 97

Slide 97 text

CASE STUDY: GAMEDEV COORDINATE SPACES

Slide 98

Slide 98 text

SOME OF THE WORLD MAY BE OFFSCREEN

Slide 99

Slide 99 text

CUSTOM TYPES type alias Point = (Int, Int) type WorldSpace = WorldSpace Point type ScreenSpace = ScreenSpace Point

Slide 100

Slide 100 text

CONVERTING BETWEEN THE TWO - VIEWPORT type alias Viewport = { position : WorldSpace , width : GameDistance , height : GameDistance }

Slide 101

Slide 101 text

renderCharacter : Viewport -> Character -> Svg a renderCharacter vp character = character.position |> toScreenCoords vp |> renderSpriteAt "character.png"

Slide 102

Slide 102 text

3 KINDS OF MISTAKES 1. Argument order 2. Unit conversion 3. Invalid operation

Slide 103

Slide 103 text

COMMUNICATE!

Slide 104

Slide 104 text

WHAT QUANTITY DOES THIS REPRESENT?

Slide 105

Slide 105 text

ENFORCE CONSTRAINTS WITH OPAQUE TYPES

Slide 106

Slide 106 text

SHARE IMPLEMENTATIONS WITH PHANTOM TYPES

Slide 107

Slide 107 text

ianmackenzie/elm- units

Slide 108

Slide 108 text

F#

Slide 109

Slide 109 text

No content