Find your Types!
Today, let's talk about types
About static types, not the others
Let's have some fun
And who knows? Maybe you will
Jordane Grenat – @JoGrenat
Picture from congerdesign
Picture from Björn Larsson, www.bjornlarsson.se
Types
const myCard = {
value: 2,
color: 'heart'
};
const myCard = {
value: 10,
color: 'spade'
};
const myCard = {
value: 11,
color: 'club'
};
const myCard = {
value: ?,
color: 'club'
};
interface Card {
value: number;
color: string;
}
11 = ?
const myCard = {
value: 83,
color: 'club'
};
const myCard = {
value: 3,
color: 'green'
};
const myCard = {
value: -1.6,
color: ''
};
A type is the
shape of a value
A type is a set of possible values
Number
3.17
-6
0
98438I9
...
Bool
True
False
Cardinality = number of possible values
(value, color)
number
string
∞
∞
X
∞
(value, color)
13
4
X
52
public enum Color {
HEART, SPADE, CLUB, DIAMOND;
};
public enum Value {
ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN,
EIGHT, NINE, TEN, JACK, QUEEN, KING;
};
public class Card {
public Value value;
public Color color;
}
public enum Color {
HEART, SPADE, CLUB, DIAMOND;
};
public enum Color {
HEART, SPADE, CLUB, DIAMOND;
};
public enum Value {
ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN,
EIGHT, NINE, TEN, JACK, QUEEN, KING;
};
13
4
52
52 cartes
+ 2 jokers
54
public enum Color {
HEART, SPADE, CLUB, DIAMOND,
BLACK, RED;
};
public enum Value {
ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN,
EIGHT, NINE, TEN, JACK, QUEEN, KING,
JOKER;
};
public class Card {
public Value value;
public Color color;
}
14
6
84
30
14 x 6 = 84
13 x 4 + 2 = 54
public class Card {
public Value value;
public Color color;
}
A card is a value AND a color
public enum Color {
HEART, SPADE, CLUB, DIAMOND;
}
public enum Color {
HEART, SPADE, CLUB, DIAMOND,
NEW_COLOR;
}
4
+ 1 = 5
A color is heart OR spade OR club OR diamond
OR new_color
AND = multiply
OR = add
What is a Card?
A card is
a color AND a value
OR a red joker
OR a black joker
public enum Card {
SIMPLE_CARD(Value, Color),
RED_JOKER,
BLACK_JOKER;
}
type Card =
SimpleCard Value Color
| RedJoker
| BlackJoker
AND = Product Type
OR = Sum Type
BOTH = Algebraic Data Type
public Order orderProduct(Product product, boolean withGiftWrap) {
// ...
}
orderProduct(book, true);
public enum GiftWrap {
NO_GIFT_WRAP, WITH_GIFT_WRAP;
}
public Order orderProduct(Product product, GiftWrap giftWrap) {
// ...
}
orderProduct(book, WITH_GIFT_WRAP);
type Card = SimpleCard | 'Red Joker' | 'Black Joker';
interface SimpleCard {
color: Color;
value: Value;
}
Picture from Tristan Schmurr, flickr.com/photos/kewl/
(value, color)
13
4
X
52
null
(13 + 1) x (4 + 1) = 70
null
(13 + 1) x (4 + 1) = 52
Nullable value
Something that is a value or is nothing
OR
type MaybeString =
Just String
| Nothing
case myString of
Just value ->
value
Nothing ->
"No value"
Picture from Tristan Schmurr, flickr.com/photos/kewl/
type Maybe a =
Just a
| Nothing
myString : Maybe String
myString = Just "Hello"
Maybe String ≠ Maybe Int
String value = "value";
Optional<String> optional = Optional.of(value);
assertTrue(optional.isPresent());
function viewName(user: User | null) {
if (user !== null) {
console.log(user.name);
}
}
with strictNullChecks
Reduce invalid inputs
try {
Files.readAllLines(filePath, UTF_8);
} catch (IOException e) {
// error handling
}
enum Result<T, E> {
Ok(T),
Err(E),
}
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error>
Try.of(() -> Files.readAllLines(filePath, UTF_8))
.getOrElse(emptyList);
Make your function total
import {ok, fail, Result} from './result.ts';
function sendEmail(email: string, content: string)
: Result<void, string> {
if (!isValid(email)) {
return fail('Invalid email');
}
// ... actually send the email
return ok(void);
}
export class Email {
private constructor(private email: string) {}
static fromString(emailString: string): Result<Email, string> {
if (isValid(emailString)) {
return fail('Invalid email');
}
return ok(new Email(emailString));
}
}
function sendEmail(email: Email, content: string): void {
// actually send email
}
- Restrict domain to avoid checks
- Make your functions total
- Explicit over implicit
Cardinality = number of possible values
card(string) = ∞
card(number) = ∞
card(bool) = 2
card(Unit) = 1
Unit Type
public enum Unit {
UNIT;
}
Usually named ()
No information
pub fn set_permissions(&self, perm: Permissions)
-> Result<(), io::Error>
No arguments
myValue : Int
myValue = 13 ^ 150
myValue : () -> Int
myValue () = 13 ^ 150
myOtherValue : Int
myOtherValue = myValue () + 2
➡ Lazy evaluation
Natural integers
myValue : List ()
myValue = []
myValue2 : List ()
myValue2 = [(), ()]
List.length myValue -- 0
List.length myValue2 -- 2
type alias NaturalInt = List ()
Bottom Type
data Void
type Never =
JustOneMore Never
myValue =
JustOneMore (JustOneMore (...))
card(Void) = 0
Impossibility
pub fn thisCannotFail(&this)
-> Result<MyResult, Void>
Non-ending
pub fn thisDoesNotEnd(&this)
-> Void
Phantom type
type Maybe a =
Just a
| Nothing
type Input a
= Value String
= Flag
type Validated = InputValidated
type NotValidated = InputNotValidated
create : String -> Input NotValidated
create value = Value value
validate : Input NotValidated -> Maybe (Input Validated)
validate (Value value) =
if isValid value then
Just (Value value)
else
Nothing
saveForm : Input Validated -> Result Error ()
myInput = create "value"
saveForm myInput
myInput = create "value"
case validate myInput of
Just validatedInput ->
saveForm validatedInput
Nothing ->
doSomethingElse
➡ Ensure workflow
type Validated =
InputValidated Never
type NotValidated =
InputNotValidated Never
type Validated =
InputValidated
type NotValidated =
InputNotValidated
type Currency a = Currency Int
type Euro = Euro Never
type UsDollar = UsDollar Never
euro : Int -> Currency Euro
euro amount = Currency amount
usDollar : Int -> Currency UsDollar
usDollar amount = Currency amount
add : Currency a -> Currency a -> Currency a
Bool
True
False
Type
Values
hand = Ace :: King :: Queen :: Jack :: Ten :: Nil
fifthCard = index 4 hand
sixthCard = index 5 hand
hand : Vect 5 Card
hand = Ace :: King :: Queen :: Jack :: Ten :: Nil
fifthCard = index 4 hand
sixthCard = index 5 hand
hand : Vect 5 Card
hand = Ace :: King :: Queen :: Jack :: Ten :: Nil
fifthCard = index 4 hand
sixthCard = index 5 hand
index : Fin n -> Vect n e -> e
Dependent types
Contraintes
Garanties
- Moins d'états impossibles
- Moins d'edge case
- Moins de bugs
- Moins de tests
Quiz Time!
function1 : a -> b
function2 : a -> a
function3 : a -> String
function4 : String -> String
0
function2 : a -> a
1
function3 : a -> String
∞
function4 : String -> String
∞
Plus de contraintes ≠ Moins de liberté
Thanks !
- Stop using string, number, bool...
- Parse, don't validate
- Watch Make impossible states impossible
Types top !
By ereold
Types top !
- 1,681