T E N TY P TA K M A
O S Y S T E M A C H T Y P Ó W N A P R Z Y K Ł A D Z I E
T Y P E S C R I P T ’ A
A R T U R S KO W R O Ń S K I  
T H E R E A R E T W O H A R D T H I N G S
I N C O M P U T E R S C I E N C E :
P H I L K A R LT O N
C A C H E I N VA L I D AT I O N
N A M I N G T H I N G S
T H E R E A R E T W O H A R D T H I N G S
I N C O M P U T E R S C I E N C E :
P H I L K A R LT O N
C A C H E I N VA L I D AT I O N
N A M I N G T H I N G S
N A M I N G T H I N G S
O N T O L O G Y
O N T O L O G Y
  " O N T O "   O Z N A C Z A „ T O , C O J E S T ” , „ C O K O LW I E K ”
I N T O W H AT C AT E G O R I E S , I F A N Y, C A N W E S O R T
E X I S T I N G T H I N G S ?
T Y P E S T H E O RY
INTEGER
SET OF

VALUES
SET OF

OPERATIONS
TYPES
INTEGER
SET OF

VALUES
SET OF

OPERATIONS
1, 2, 3, 4, 5, 

6, 7, 8, 9, 10…
NO IMPOSSIBLE VALUES
INTEGER
TYPES
SET OF

VALUES
SET OF

OPERATIONS
INTEGER
NO IMPOSSIBLE OPERATIONS
SET OF

OPERATIONS
+, -, /, *
SET OF

VALUES
DIVISION ON INTEGER?
SET OF

OPERATIONS
INTEGER
+, -, /, *
SET OF

VALUES
W E A K & S T R O N G T Y P I N G
L I G H T W E I G H T T E C H N O L O G Y
S TAT I C & D Y N A M I C T Y P I N G
S TAT I C T Y P I N G
ASSEMBLER
HOW CAN WE PROVE THAT THIS PROGRAM WORKS?
RICE’S THEOREM (1957)
KAŻDA NIETRYWIALNA WŁASNOŚĆ JĘZYKÓW REKURENCYJNIE PRZELICZALNYCH JEST NIEROZSTRZYGALNA
S E T O F R U L E S
F O R T R A N ( 1 9 5 7 )
D ATA A R E A N N O TAT E D W I T H T Y P E I N F O
S E L F - D O C U M E N TAT I O N
F O R H U M A N S
F O R M A C H I N E S
A N Y F O O L C A N W R I T E C O D E
T H AT A C O M P U T E R C A N
U N D E R S TA N D . G O O D
P R O G R A M M E R S W R I T E C O D E
T H AT H U M A N S C A N
U N D E R S TA N D .
M A R T I N F O W L E R
S TAT I C F I L E C H E C K I N G D O N E O N C O M P I L AT I O N T I M E
SOURCE
CODE
TYPE CHECKER
TYPE CHECKER
T Y P E C H E C K E R P R O V E S C H O S E N P R O P E R T I E S
“PROVEN”
CODE
TYPE CHECKER
D O N ’ T N E E D T O B E I N C O R R E C T
?
PERFECTLY VALID PROGRAM…
let stringValue: unknown = "Value";
stringValue.trim();
…STILL WILL FAIL
let stringValue: unknown = "Value";
stringValue.trim();
…STILL WILL FAIL
let stringValue: unknown = "Value";
stringValue.trim();
L O W E R B O N D O F C O R R E C T N E S S
T R A D E O F F : E A S Y T O U S E / C O R R E C T
DIVISION ON INTEGER?
SET OF

VALUES
SET OF

OPERATIONS
SUPER-STRICT-INTEGER
+, -, /, *
N O T Y P E S I N R U N T I M E
S TAT I C & D Y N A M I C T Y P I N G
D Y N A M I C T Y P I N G
HOW CAN WE PROVE THAT THIS PROGRAM WORKS?
P R O B L E M - N O I N F O A B O U T T Y P E S I N R U N T I M E
VA R I A B L E I N C O D E
int variable = 1
RUNTIME
RUNTIME
D E C O R AT E D W I T H T Y P E O N R U N T I M E
value = 1
type = int
variable
E V E RY T H I N G I S C O R R E C T
RUNTIME
Math.abs()
value = 1
type = int
variable
R U N T I M E E X C E P T I O N
value = 1
type = int
variable
String.trim()
RUNTIME
P E R F O R M A N C E
G R A D U A L T Y P I N G
S TAT I C C O R E
D Y N A M I C N E W C O D E ( W I T H A N Y )
I N T E R O P E R A B I L I T Y W I T H J AVA S C R I P T
T Y P E E R A S U R E
S T R U C T U R A L T Y P I N G
N O M I N A L T Y P I N G
class Foo {
method(input: string): number { ... }
}
class Bar {
method(input: string): number { ... }
}
let foo: Foo = new Bar();
N O M I N A L T Y P I N G
class Foo {
method(input: string): number { ... }
}
class Bar {
method(input: string): number { ... }
}
let foo: Foo = new Bar();
N O M I N A L T Y P I N G
class Foo {
method(input: string): number { ... }
}
class Bar {
method(input: string): number { ... }
}
let foo: Foo = new Bar();
S T R U C T U R A L T Y P I N G
class Foo {
method(input: string): number { ... }
}
class Bar {
method(input: string): number { ... }
}
let foo: Foo = new Bar();
S T R U C T U R A L T Y P I N G
class Foo {
method(input: string): number { ... }
}
class Bar {
method(input: string): number { ... }
}
let foo: Foo = new Bar();
E X P L I C I T T Y P I N G
let foo: Foo = new Foo();let foo: Foo = new Foo();
M L & H I N D L E Y – M I L N E R M E T H O D
T Y P E I N F E R E N C E
IMPLICIT TYPING
let foo = new Foo();
WHAT-A-TYPE?
let a = 'x'
let b = true
let c = 3
WHAT-A-TYPE?
let a = 'x' //string
let b = true //boolean
let c = 3 //number
WHAT-A-TYPE?
const a = 'x'
const b = true
const c = 3
WHAT-A-TYPE?
const a = 'x' // ‘x’
const b = true // true
const c = 3 // 3
WITHOUT TYPE OF GUARD
let stringValue: unknown =
"Value";
stringValue.trim()
TYPE OF GUARD
function withTypeGuards(value: unknown) {
if (typeof value === "string") {
return value.trim();
}
}
TYPE OF GUARD
function withTypeGuards(value: unknown) {
if (typeof value === "string") {
return value.trim();
}
}
TYPE OF GUARD
function withTypeGuards(value: unknown) {
if (typeof value === "string") {
return value.trim();
}
}
TYPE OF GUARD
function withTypeGuards(value: unknown) {
if (typeof value === "string") {
return value.trim(); // string
}
}
PA R A M E T R I Z E D P O LY M O R P H I S M
E X . A R R AY S
let message: Array<string> = []
message.push("test");
message.push(2);
E X . A R R AY S
let message: Array<string> = []
message.push("test");
message.push(2);
E X . A R R AY S
let message: Array<string> = []
message.push("test");
message.push(2);
E X . A R R AY S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
unsafeAdd(message)
const el: string = message[0]
console.log(el.toLowerCase())
U N S O U N D T Y P E S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
unsafeAdd(message)
const el: string = message[1]
console.log(el.toLowerCase())
U N S O U N D T Y P E S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
unsafeAdd(message)
const el: string = message[1]
console.log(el.toLowerCase())
U N S O U N D T Y P E S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
unsafeAdd(message)
const el: string = message[1]
console.log(el.toLowerCase())
U N S O U N D T Y P E S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
unsafeAdd(message)
const el: string = message[1]
console.log(el.toLowerCase())
U N S O U N D T Y P E S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
const el: string = message[1]
console.log(el.toLowerCase())
U N S O U N D T Y P E S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
unsafeAdd(message)
const el: string = message[1]
console.log(el.toLowerCase())
U N S O U N D T Y P E S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
unsafeAdd(message)
const el: string = message[1]
console.log(el.toLowerCase())
U N S O U N D T Y P E S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
unsafeAdd(message)
const el: string = message[0]
console.log(el.toLowerCase())
U N S O U N D T Y P E S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
unsafeAdd(message)
const el: string = message[0]
console.log(el.toLowerCase())
U N S O U N D T Y P E S
function unsafeAdd(arr: Array<string | number>): void {
arr.push(3)
}
let message: Array<string> = []
unsafeAdd(message)
const el: string = message[0]
console.log(el.toLowerCase()) / int
VA L I D J S C O D E
function unsafeAdd(arr) {
arr.push(3)
}
var message = []
unsafeAdd(message)
var el = message[0]
console.log(el.toLowerCase())
S O U N D ?
H O W T O M A K E I T S O U N D
function checkIfTypeOk(el, type) {
if(!el instanceof type) throw new ClassCastException()
}
var message: Array<string> = []
unsafeAdd(message)
var el = message[0]
checkIfTypeOk(el, string)
console.log(el.toLowerCase())
H O W T O M A K E I T S O U N D
function checkIfTypeOk(el, type) {
if(!el instanceof type) throw new ClassCastException()
}
var message: Array<string> = []
unsafeAdd(message)
var el = message[0]
checkIfTypeOk(el, string)
console.log(el.toLowerCase())
H O W T O M A K E I T S O U N D
function checkIfTypeOk(el, type) {
if(!el instanceof type) throw new ClassCastException()
}
var message: Array<string> = []
unsafeAdd(message)
var el = message[0]
checkIfTypeOk(el, string)
console.log(el.toLowerCase())
H O W T O M A K E I T S O U N D
function checkIfTypeOk(el, type) {
if(!el instanceof type) throw new ClassCastException()
}
var message: Array<string> = []
unsafeAdd(message)
var el = message[0]
checkIfTypeOk(el, string)
console.log(el.toLowerCase())
T R A D E O F F : E A S Y T O U S E / C O R R E C T
C O M PAT I B L E W I T H J S
GRADUAL (STATIC WITH TYPE ERASURE)
STRUCTURALLY TYPED IMPLICITELY TYPED UNSOUND
S O U R C E S
https://www2.ccs.neu.edu/racket/pubs/ecoop2015-takikawa-et-al.pdf
https://users.soe.ucsc.edu/~abadi/Papers/FTS-submitted.pdf
UNDERSTANDING TYPESCRIPT
https://blog.steveklabnik.com/posts/2010-07-17-what-to-know-before-debating-type-systems
WHAT TO KNOW BEFORE DEBATING TYPE SYSTEMS
TOWARDS PRACTICAL GRADUAL TYPING
https://papl.cs.brown.edu/2014/safety-soundness.html
SAFETY AND SOUNDNESS
S O U R C E S
https://www2.ccs.neu.edu/racket/pubs/ecoop2015-takikawa-et-al.pdf
https://users.soe.ucsc.edu/~abadi/Papers/FTS-submitted.pdf
UNDERSTANDING TYPESCRIPT
https://blog.steveklabnik.com/posts/2010-07-17-what-to-know-before-debating-type-systems
WHAT TO KNOW BEFORE DEBATING TYPE SYSTEMS
TOWARDS PRACTICAL GRADUAL TYPING
https://papl.cs.brown.edu/2014/safety-soundness.html
SAFETY AND SOUNDNESS
Q U E S T I O N S ?
T H A N K Y O U !

Ten Typ tak ma - O systemach typów na przykładzie TypeScript’a

  • 1.
    T E NTY P TA K M A O S Y S T E M A C H T Y P Ó W N A P R Z Y K Ł A D Z I E T Y P E S C R I P T ’ A A R T U R S KO W R O Ń S K I  
  • 2.
    T H ER E A R E T W O H A R D T H I N G S I N C O M P U T E R S C I E N C E : P H I L K A R LT O N C A C H E I N VA L I D AT I O N N A M I N G T H I N G S
  • 3.
    T H ER E A R E T W O H A R D T H I N G S I N C O M P U T E R S C I E N C E : P H I L K A R LT O N C A C H E I N VA L I D AT I O N N A M I N G T H I N G S
  • 4.
    N A MI N G T H I N G S
  • 5.
    O N TO L O G Y
  • 6.
    O N TO L O G Y   " O N T O "   O Z N A C Z A „ T O , C O J E S T ” , „ C O K O LW I E K ”
  • 7.
    I N TO W H AT C AT E G O R I E S , I F A N Y, C A N W E S O R T E X I S T I N G T H I N G S ?
  • 9.
    T Y PE S T H E O RY
  • 10.
  • 11.
    INTEGER SET OF
 VALUES SET OF
 OPERATIONS 1,2, 3, 4, 5, 
 6, 7, 8, 9, 10… NO IMPOSSIBLE VALUES
  • 12.
  • 13.
    INTEGER NO IMPOSSIBLE OPERATIONS SETOF
 OPERATIONS +, -, /, * SET OF
 VALUES
  • 14.
    DIVISION ON INTEGER? SETOF
 OPERATIONS INTEGER +, -, /, * SET OF
 VALUES
  • 15.
    W E AK & S T R O N G T Y P I N G
  • 16.
    L I GH T W E I G H T T E C H N O L O G Y
  • 17.
    S TAT IC & D Y N A M I C T Y P I N G
  • 18.
    S TAT IC T Y P I N G
  • 19.
  • 20.
    HOW CAN WEPROVE THAT THIS PROGRAM WORKS?
  • 21.
    RICE’S THEOREM (1957) KAŻDANIETRYWIALNA WŁASNOŚĆ JĘZYKÓW REKURENCYJNIE PRZELICZALNYCH JEST NIEROZSTRZYGALNA
  • 22.
    S E TO F R U L E S
  • 23.
    F O RT R A N ( 1 9 5 7 )
  • 24.
    D ATA AR E A N N O TAT E D W I T H T Y P E I N F O
  • 25.
    S E LF - D O C U M E N TAT I O N
  • 26.
    F O RH U M A N S
  • 27.
    F O RM A C H I N E S
  • 28.
    A N YF O O L C A N W R I T E C O D E T H AT A C O M P U T E R C A N U N D E R S TA N D . G O O D P R O G R A M M E R S W R I T E C O D E T H AT H U M A N S C A N U N D E R S TA N D . M A R T I N F O W L E R
  • 29.
    S TAT IC F I L E C H E C K I N G D O N E O N C O M P I L AT I O N T I M E SOURCE CODE TYPE CHECKER
  • 30.
    TYPE CHECKER T YP E C H E C K E R P R O V E S C H O S E N P R O P E R T I E S “PROVEN” CODE
  • 31.
    TYPE CHECKER D ON ’ T N E E D T O B E I N C O R R E C T ?
  • 32.
    PERFECTLY VALID PROGRAM… letstringValue: unknown = "Value"; stringValue.trim();
  • 33.
    …STILL WILL FAIL letstringValue: unknown = "Value"; stringValue.trim();
  • 34.
    …STILL WILL FAIL letstringValue: unknown = "Value"; stringValue.trim();
  • 35.
    L O WE R B O N D O F C O R R E C T N E S S
  • 36.
    T R AD E O F F : E A S Y T O U S E / C O R R E C T
  • 37.
    DIVISION ON INTEGER? SETOF
 VALUES SET OF
 OPERATIONS SUPER-STRICT-INTEGER +, -, /, *
  • 38.
    N O TY P E S I N R U N T I M E
  • 39.
    S TAT IC & D Y N A M I C T Y P I N G
  • 40.
    D Y NA M I C T Y P I N G
  • 41.
    HOW CAN WEPROVE THAT THIS PROGRAM WORKS?
  • 42.
    P R OB L E M - N O I N F O A B O U T T Y P E S I N R U N T I M E
  • 43.
    VA R IA B L E I N C O D E int variable = 1 RUNTIME
  • 44.
    RUNTIME D E CO R AT E D W I T H T Y P E O N R U N T I M E value = 1 type = int variable
  • 45.
    E V ERY T H I N G I S C O R R E C T RUNTIME Math.abs() value = 1 type = int variable
  • 46.
    R U NT I M E E X C E P T I O N value = 1 type = int variable String.trim() RUNTIME
  • 47.
    P E RF O R M A N C E
  • 48.
    G R AD U A L T Y P I N G
  • 49.
    S TAT IC C O R E
  • 50.
    D Y NA M I C N E W C O D E ( W I T H A N Y )
  • 51.
    I N TE R O P E R A B I L I T Y W I T H J AVA S C R I P T
  • 52.
    T Y PE E R A S U R E
  • 53.
    S T RU C T U R A L T Y P I N G
  • 54.
    N O MI N A L T Y P I N G class Foo { method(input: string): number { ... } } class Bar { method(input: string): number { ... } } let foo: Foo = new Bar();
  • 55.
    N O MI N A L T Y P I N G class Foo { method(input: string): number { ... } } class Bar { method(input: string): number { ... } } let foo: Foo = new Bar();
  • 56.
    N O MI N A L T Y P I N G class Foo { method(input: string): number { ... } } class Bar { method(input: string): number { ... } } let foo: Foo = new Bar();
  • 57.
    S T RU C T U R A L T Y P I N G class Foo { method(input: string): number { ... } } class Bar { method(input: string): number { ... } } let foo: Foo = new Bar();
  • 58.
    S T RU C T U R A L T Y P I N G class Foo { method(input: string): number { ... } } class Bar { method(input: string): number { ... } } let foo: Foo = new Bar();
  • 59.
    E X PL I C I T T Y P I N G let foo: Foo = new Foo();let foo: Foo = new Foo();
  • 60.
    M L &H I N D L E Y – M I L N E R M E T H O D T Y P E I N F E R E N C E
  • 61.
  • 62.
    WHAT-A-TYPE? let a ='x' let b = true let c = 3
  • 63.
    WHAT-A-TYPE? let a ='x' //string let b = true //boolean let c = 3 //number
  • 64.
    WHAT-A-TYPE? const a ='x' const b = true const c = 3
  • 65.
    WHAT-A-TYPE? const a ='x' // ‘x’ const b = true // true const c = 3 // 3
  • 66.
    WITHOUT TYPE OFGUARD let stringValue: unknown = "Value"; stringValue.trim()
  • 67.
    TYPE OF GUARD functionwithTypeGuards(value: unknown) { if (typeof value === "string") { return value.trim(); } }
  • 68.
    TYPE OF GUARD functionwithTypeGuards(value: unknown) { if (typeof value === "string") { return value.trim(); } }
  • 69.
    TYPE OF GUARD functionwithTypeGuards(value: unknown) { if (typeof value === "string") { return value.trim(); } }
  • 70.
    TYPE OF GUARD functionwithTypeGuards(value: unknown) { if (typeof value === "string") { return value.trim(); // string } }
  • 71.
    PA R AM E T R I Z E D P O LY M O R P H I S M
  • 72.
    E X .A R R AY S let message: Array<string> = [] message.push("test"); message.push(2);
  • 73.
    E X .A R R AY S let message: Array<string> = [] message.push("test"); message.push(2);
  • 74.
    E X .A R R AY S let message: Array<string> = [] message.push("test"); message.push(2);
  • 75.
    E X .A R R AY S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] unsafeAdd(message) const el: string = message[0] console.log(el.toLowerCase())
  • 76.
    U N SO U N D T Y P E S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] unsafeAdd(message) const el: string = message[1] console.log(el.toLowerCase())
  • 77.
    U N SO U N D T Y P E S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] unsafeAdd(message) const el: string = message[1] console.log(el.toLowerCase())
  • 78.
    U N SO U N D T Y P E S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] unsafeAdd(message) const el: string = message[1] console.log(el.toLowerCase())
  • 79.
    U N SO U N D T Y P E S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] unsafeAdd(message) const el: string = message[1] console.log(el.toLowerCase())
  • 80.
    U N SO U N D T Y P E S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] const el: string = message[1] console.log(el.toLowerCase())
  • 81.
    U N SO U N D T Y P E S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] unsafeAdd(message) const el: string = message[1] console.log(el.toLowerCase())
  • 82.
    U N SO U N D T Y P E S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] unsafeAdd(message) const el: string = message[1] console.log(el.toLowerCase())
  • 83.
    U N SO U N D T Y P E S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] unsafeAdd(message) const el: string = message[0] console.log(el.toLowerCase())
  • 84.
    U N SO U N D T Y P E S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] unsafeAdd(message) const el: string = message[0] console.log(el.toLowerCase())
  • 85.
    U N SO U N D T Y P E S function unsafeAdd(arr: Array<string | number>): void { arr.push(3) } let message: Array<string> = [] unsafeAdd(message) const el: string = message[0] console.log(el.toLowerCase()) / int
  • 86.
    VA L ID J S C O D E function unsafeAdd(arr) { arr.push(3) } var message = [] unsafeAdd(message) var el = message[0] console.log(el.toLowerCase())
  • 87.
    S O UN D ?
  • 88.
    H O WT O M A K E I T S O U N D function checkIfTypeOk(el, type) { if(!el instanceof type) throw new ClassCastException() } var message: Array<string> = [] unsafeAdd(message) var el = message[0] checkIfTypeOk(el, string) console.log(el.toLowerCase())
  • 89.
    H O WT O M A K E I T S O U N D function checkIfTypeOk(el, type) { if(!el instanceof type) throw new ClassCastException() } var message: Array<string> = [] unsafeAdd(message) var el = message[0] checkIfTypeOk(el, string) console.log(el.toLowerCase())
  • 90.
    H O WT O M A K E I T S O U N D function checkIfTypeOk(el, type) { if(!el instanceof type) throw new ClassCastException() } var message: Array<string> = [] unsafeAdd(message) var el = message[0] checkIfTypeOk(el, string) console.log(el.toLowerCase())
  • 91.
    H O WT O M A K E I T S O U N D function checkIfTypeOk(el, type) { if(!el instanceof type) throw new ClassCastException() } var message: Array<string> = [] unsafeAdd(message) var el = message[0] checkIfTypeOk(el, string) console.log(el.toLowerCase())
  • 92.
    T R AD E O F F : E A S Y T O U S E / C O R R E C T C O M PAT I B L E W I T H J S
  • 93.
    GRADUAL (STATIC WITHTYPE ERASURE) STRUCTURALLY TYPED IMPLICITELY TYPED UNSOUND
  • 94.
    S O UR C E S https://www2.ccs.neu.edu/racket/pubs/ecoop2015-takikawa-et-al.pdf https://users.soe.ucsc.edu/~abadi/Papers/FTS-submitted.pdf UNDERSTANDING TYPESCRIPT https://blog.steveklabnik.com/posts/2010-07-17-what-to-know-before-debating-type-systems WHAT TO KNOW BEFORE DEBATING TYPE SYSTEMS TOWARDS PRACTICAL GRADUAL TYPING https://papl.cs.brown.edu/2014/safety-soundness.html SAFETY AND SOUNDNESS
  • 95.
    S O UR C E S https://www2.ccs.neu.edu/racket/pubs/ecoop2015-takikawa-et-al.pdf https://users.soe.ucsc.edu/~abadi/Papers/FTS-submitted.pdf UNDERSTANDING TYPESCRIPT https://blog.steveklabnik.com/posts/2010-07-17-what-to-know-before-debating-type-systems WHAT TO KNOW BEFORE DEBATING TYPE SYSTEMS TOWARDS PRACTICAL GRADUAL TYPING https://papl.cs.brown.edu/2014/safety-soundness.html SAFETY AND SOUNDNESS Q U E S T I O N S ? T H A N K Y O U !