1. Virtual ECOOP 2022
Direct Foundations for
Compositional Programming
Andong Fan*, Xuejing Huang*,
Han Xu, Yaozhu Sun, and Bruno C. d. S. Oliveira
*equal contributions
3. Expression Problem
Background
2
Describes the dilemma of modular extension
of datatypes and their operations
e.g. extending simple arithmetic expressions and their operations…
OOP FP
4. Expression Problem
Background
2
Describes the dilemma of modular extension
of datatypes and their operations
// class hierarchy
trait Exp {
def eval: Int
}
class Lit(n: Int) extends Exp {
def eval: Int = n
}
class Sub(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval - r.eval
}
new Sub(new Lit(1), new Lit(2)).eval
e.g. extending simple arithmetic expressions and their operations…
OOP FP
5. Expression Problem
Background
2
Describes the dilemma of modular extension
of datatypes and their operations
// class hierarchy
trait Exp {
def eval: Int
}
class Lit(n: Int) extends Exp {
def eval: Int = n
}
class Sub(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval - r.eval
}
new Sub(new Lit(1), new Lit(2)).eval
// algebraic datatype
sealed trait Exp
case class Lit(n: Int) extends Exp
case class Sub(l: Exp, r: Exp) extends Exp
// pattern matching function
def eval(exp: Exp): Int = exp match {
case Lit(n) => n
case Sub(l, r) => eval(l) - eval(r)
}
eval(Sub(Lit(1), Lit(2)))
e.g. extending simple arithmetic expressions and their operations…
OOP FP
6. Expression Problem
3
of datatypes and their operations
// class hierarchy
trait Exp {
def eval: Int
}
class Lit(n: Int) extends Exp {
def eval: Int = n
}
class Sub(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval - r.eval
}
class Add(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval + r.eval
}
new Sub(new Lit(1), new Lit(2)).eval
Modular!
OOP FP
Describes the dilemma of modular extension
e.g. extending simple arithmetic expressions and their operations…
// algebraic datatype
sealed trait Exp
case class Lit(n: Int) extends Exp
case class Sub(l: Exp, r: Exp) extends Exp
// pattern matching function
def eval(exp: Exp): Int = exp match {
case Lit(n) => n
case Sub(l, r) => eval(l) - eval(r)
}
eval(Sub(Lit(1), Lit(2)))
Background
7. Expression Problem
4
of datatypes and their operations
trait Exp {
def eval: Int
def print: String
}
class Lit(n: Int) extends Exp {
def eval: Int = n
def print: String = ..
}
class Sub(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval - r.eval
def print: String = ..
}
class Add(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval + r.eval
def print: String = ..
}
new Sub(new Lit(1), new Lit(2)).eval
OOP FP
Non-Modular!
Non-Modular!
Non-Modular!
Non-Modular!
Describes the dilemma of modular extension
e.g. extending simple arithmetic expressions and their operations…
// algebraic datatype
sealed trait Exp
case class Lit(n: Int) extends Exp
case class Sub(l: Exp, r: Exp) extends Exp
// pattern matching function
def eval(exp: Exp): Int = exp match {
case Lit(n) => n
case Sub(l, r) => eval(l) - eval(r)
}
eval(Sub(Lit(1), Lit(2)))
Background
8. Expression Problem
4
of datatypes and their operations
trait Exp {
def eval: Int
def print: String
}
class Lit(n: Int) extends Exp {
def eval: Int = n
def print: String = ..
}
class Sub(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval - r.eval
def print: String = ..
}
class Add(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval + r.eval
def print: String = ..
}
new Sub(new Lit(1), new Lit(2)).eval
OOP FP
Non-Modular!
Non-Modular!
Non-Modular!
Non-Modular!
Modular extension of
Datatypes ✅
Operations ❌
Describes the dilemma of modular extension
e.g. extending simple arithmetic expressions and their operations…
// algebraic datatype
sealed trait Exp
case class Lit(n: Int) extends Exp
case class Sub(l: Exp, r: Exp) extends Exp
// pattern matching function
def eval(exp: Exp): Int = exp match {
case Lit(n) => n
case Sub(l, r) => eval(l) - eval(r)
}
eval(Sub(Lit(1), Lit(2)))
Background
9. Expression Problem
5
of datatypes and their operations
trait Exp {
def eval: Int
def print: String
}
class Lit(n: Int) extends Exp {
def eval: Int = n
def print: String = ..
}
class Sub(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval - r.eval
def print: String = ..
}
class Add(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval + r.eval
def print: String = ..
}
new Sub(new Lit(1), new Lit(2)).eval
// algebraic datatype
sealed trait Exp
case class Lit(n: Int) extends Exp
case class Sub(l: Exp, r: Exp) extends Exp
// pattern matching function
def eval(exp: Exp): Int = exp match {
case Lit(n) => n
case Sub(l, r) => eval(l) - eval(r)
}
def print(exp: Exp): String = exp match {
case Lit(n) => ..
case Sub(l, r) => ..
}
eval(Sub(Lit(1), Lit(2)))
OOP FP
Non-Modular!
Non-Modular!
Non-Modular!
Non-Modular!
Modular extension of
Datatypes ✅
Operations ❌
Describes the dilemma of modular extension
Modular!
e.g. extending simple arithmetic expressions and their operations…
Background
10. Expression Problem
6
of datatypes and their operations
trait Exp {
def eval: Int
def print: String
}
class Lit(n: Int) extends Exp {
def eval: Int = n
def print: String = ..
}
class Sub(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval - r.eval
def print: String = ..
}
class Add(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval + r.eval
def print: String = ..
}
new Sub(new Lit(1), new Lit(2)).eval
sealed trait Exp
case class Lit(n: Int) extends Exp
case class Sub(l: Exp, r: Exp) extends Exp
case class Add(l: Exp, r: Exp) extends Exp
// pattern matching function
def eval(exp: Exp): Int = exp match {
case Lit(n) => n
case Sub(l, r) => eval(l) - eval(r)
case Add(l, r) => ..
}
def print(exp: Exp): String = exp match {
case Lit(n) => ..
case Sub(l, r) => ..
case Add(l, r) => ..
}
eval(Sub(Lit(1), Lit(2)))
OOP FP
Non-Modular!
Non-Modular!
Non-Modular!
Non-Modular!
Modular extension of
Datatypes ✅
Operations ❌
Describes the dilemma of modular extension
Non-Modular!
Non-Modular!
Non-Modular!
e.g. extending simple arithmetic expressions and their operations…
Background
11. Expression Problem
6
of datatypes and their operations
trait Exp {
def eval: Int
def print: String
}
class Lit(n: Int) extends Exp {
def eval: Int = n
def print: String = ..
}
class Sub(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval - r.eval
def print: String = ..
}
class Add(l: Exp, r: Exp) extends Exp {
def eval: Int = l.eval + r.eval
def print: String = ..
}
new Sub(new Lit(1), new Lit(2)).eval
sealed trait Exp
case class Lit(n: Int) extends Exp
case class Sub(l: Exp, r: Exp) extends Exp
case class Add(l: Exp, r: Exp) extends Exp
// pattern matching function
def eval(exp: Exp): Int = exp match {
case Lit(n) => n
case Sub(l, r) => eval(l) - eval(r)
case Add(l, r) => ..
}
def print(exp: Exp): String = exp match {
case Lit(n) => ..
case Sub(l, r) => ..
case Add(l, r) => ..
}
eval(Sub(Lit(1), Lit(2)))
OOP FP
Non-Modular!
Non-Modular!
Non-Modular!
Non-Modular!
Modular extension of
Datatypes ✅
Operations ❌
Describes the dilemma of modular extension
Non-Modular!
Non-Modular!
Non-Modular!
Modular extension of
Datatypes ❌
Operations ✅
e.g. extending simple arithmetic expressions and their operations…
Background
12. Compositional Programming*
7
Background
Provides natural solutions to the Expression Problem
Employs intersection types, a merge operator, and
fi
rst-class traits
Novel programming paradigm featuring modularity
*Weixin Zhang, Yaozhu Sun, and Bruno C. d. S. Oliveira. Compositional programming.
ACM Transactions on Programming Languages and Systems (TOPLAS), 43(3):1–61, 2021.
15. Compositional Programming
8
• Intersection types
• Merge operator
• First-class traits
Compose types with &
e.g. {a : A} & {b : B} == {a : A ; b : B}
Background
Novel programming paradigm featuring modularity
16. Compositional Programming
8
• Intersection types
• Merge operator
• First-class traits
Compose types with &
e.g. {a : A} & {b : B} == {a : A ; b : B}
Compose terms with ,,
Introductory structure of intersection types
Background
Novel programming paradigm featuring modularity
17. Compositional Programming
8
• Intersection types
• Merge operator
• First-class traits
Compose types with &
e.g. {a : A} & {b : B} == {a : A ; b : B}
Compose terms with ,,
Introductory structure of intersection types
e.g. 1 ,, true has type Int & Bool
Background
Novel programming paradigm featuring modularity
18. Compositional Programming
8
• Intersection types
• Merge operator
• First-class traits
Compose types with &
e.g. {a : A} & {b : B} == {a : A ; b : B}
Compose terms with ,,
Introductory structure of intersection types
e.g. 1 ,, true has type Int & Bool
Basic structures of Composition Programming
Background
Novel programming paradigm featuring modularity
19. The CP Language
9
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
Background
Note: In CP the merge operator is `,` while it’s originally `,,`
20. The CP Language
9
evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Eval = { eval: Int };
Background
Note: In CP the merge operator is `,` while it’s originally `,,`
21. The CP Language
9
evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
Background
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
Note: In CP the merge operator is `,` while it’s originally `,,`
22. The CP Language
9
evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
exp = new (repoNum @(Eval & Print) , evalNum , printNum);
repoNum Exp = trait [self: NumSig<Exp>] => {
num = Add (Lit 2) (Lit 3);
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
Background
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
Note: In CP the merge operator is `,` while it’s originally `,,`
23. The CP Language
9
evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
exp = new (repoNum @(Eval & Print) , evalNum , printNum);
repoNum Exp = trait [self: NumSig<Exp>] => {
num = Add (Lit 2) (Lit 3);
}; Merge operator
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
Background
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
Note: In CP the merge operator is `,` while it’s originally `,,`
24. The CP Language
9
evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
exp = new (repoNum @(Eval & Print) , evalNum , printNum);
repoNum Exp = trait [self: NumSig<Exp>] => {
num = Add (Lit 2) (Lit 3);
};
Intersection type argument
Merge operator
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
Background
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
Note: In CP the merge operator is `,` while it’s originally `,,`
25. The CP Language
9
evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
exp = new (repoNum @(Eval & Print) , evalNum , printNum);
repoNum Exp = trait [self: NumSig<Exp>] => {
num = Add (Lit 2) (Lit 3);
};
Intersection type argument
Merge operator
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
exp.num.eval —> 5
exp.num.print —> “2+3”
Background
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
Note: In CP the merge operator is `,` while it’s originally `,,`
26. evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
type MulSig<Exp> = {
Mul: Exp -> Exp -> Exp;
};
Background
The CP Language
10
Note: In CP the merge operator is `,` while it’s originally `,,`
27. evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
type MulSig<Exp> = {
Mul: Exp -> Exp -> Exp;
};
type ExpSig<Exp> =
NumSig<Exp> & MulSig<Exp>;
Background
Intersection type
The CP Language
10
Note: In CP the merge operator is `,` while it’s originally `,,`
28. evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
type MulSig<Exp> = {
Mul: Exp -> Exp -> Exp;
}; evalMul = trait implements MulSig<Eval> => {
(Mul e1 e2).eval = e1.eval * e2.eval;
};
type ExpSig<Exp> =
NumSig<Exp> & MulSig<Exp>;
Background
Intersection type
The CP Language
10
Note: In CP the merge operator is `,` while it’s originally `,,`
29. evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
type MulSig<Exp> = {
Mul: Exp -> Exp -> Exp;
}; evalMul = trait implements MulSig<Eval> => {
(Mul e1 e2).eval = e1.eval * e2.eval;
};
printMul = trait implements MulSig<Print> => {
(Mul e1 e2).print = e1.print ++ "*" ++ e2.print;
};
type ExpSig<Exp> =
NumSig<Exp> & MulSig<Exp>;
Background
Intersection type
The CP Language
10
Note: In CP the merge operator is `,` while it’s originally `,,`
30. evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
type MulSig<Exp> = {
Mul: Exp -> Exp -> Exp;
}; evalMul = trait implements MulSig<Eval> => {
(Mul e1 e2).eval = e1.eval * e2.eval;
};
printMul = trait implements MulSig<Print> => {
(Mul e1 e2).print = e1.print ++ "*" ++ e2.print;
};
type ExpSig<Exp> =
NumSig<Exp> & MulSig<Exp>;
repoExp Exp = trait [self: ExpSig<Exp>] => {
mul = Mul (Lit 2) (Lit 3)
};
Background
Intersection type
The CP Language
10
Note: In CP the merge operator is `,` while it’s originally `,,`
31. evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
type MulSig<Exp> = {
Mul: Exp -> Exp -> Exp;
}; evalMul = trait implements MulSig<Eval> => {
(Mul e1 e2).eval = e1.eval * e2.eval;
};
printMul = trait implements MulSig<Print> => {
(Mul e1 e2).print = e1.print ++ "*" ++ e2.print;
};
type ExpSig<Exp> =
NumSig<Exp> & MulSig<Exp>;
repoExp Exp = trait [self: ExpSig<Exp>] => {
mul = Mul (Lit 2) (Lit 3)
};
exp' = new (repoExp @(Eval & Print) ,
evalNum , evalMul , printNum , printMul);
Background
Intersection type
Merge operator
The CP Language
10
Note: In CP the merge operator is `,` while it’s originally `,,`
32. evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
type MulSig<Exp> = {
Mul: Exp -> Exp -> Exp;
}; evalMul = trait implements MulSig<Eval> => {
(Mul e1 e2).eval = e1.eval * e2.eval;
};
printMul = trait implements MulSig<Print> => {
(Mul e1 e2).print = e1.print ++ "*" ++ e2.print;
};
type ExpSig<Exp> =
NumSig<Exp> & MulSig<Exp>;
repoExp Exp = trait [self: ExpSig<Exp>] => {
mul = Mul (Lit 2) (Lit 3)
};
exp' = new (repoExp @(Eval & Print) ,
evalNum , evalMul , printNum , printMul);
exp'.num.eval —> 6
exp'.num.print —> “2*3”
Background
Intersection type
Merge operator
The CP Language
10
Note: In CP the merge operator is `,` while it’s originally `,,`
33. evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
type MulSig<Exp> = {
Mul: Exp -> Exp -> Exp;
}; evalMul = trait implements MulSig<Eval> => {
(Mul e1 e2).eval = e1.eval * e2.eval;
};
printMul = trait implements MulSig<Print> => {
(Mul e1 e2).print = e1.print ++ "*" ++ e2.print;
};
type ExpSig<Exp> =
NumSig<Exp> & MulSig<Exp>;
repoExp Exp = trait [self: ExpSig<Exp>] => {
mul = Mul (Lit 2) (Lit 3)
};
exp' = new (repoExp @(Eval & Print) ,
evalNum , evalMul , printNum , printMul);
exp'.num.eval —> 6
exp'.num.print —> “2*3”
Background
Intersection type
Merge operator
The CP Language
10
Note: In CP the merge operator is `,` while it’s originally `,,`
repoExp
+ mul
Lit
+ eval
evalNum
Add
+ eval
printNum
Lit
+ print
Add
+ print
evalMul
Mul
+ eval
printMul
Mul
+ print
, , , ,
=
Lit
+ eval
+ print
exp
Mul
+ eval
+ print
Add
+ eval
+ print
+ mul
34. evalNum = trait implements NumSig<Eval> => {
(Lit n).eval = n;
(Add e1 e2).eval = e1.eval + e2.eval;
};
printNum = trait implements NumSig<Print> => {
(Lit n).print = toString n;
(Add e1 e2).print = e1.print ++ "+" ++
e2.print;
};
type NumSig<Exp> = {
Lit: Int -> Exp;
Add: Exp -> Exp -> Exp;
};
type Print = { print: String };
type Eval = { eval: Int };
type MulSig<Exp> = {
Mul: Exp -> Exp -> Exp;
}; evalMul = trait implements MulSig<Eval> => {
(Mul e1 e2).eval = e1.eval * e2.eval;
};
printMul = trait implements MulSig<Print> => {
(Mul e1 e2).print = e1.print ++ "*" ++ e2.print;
};
type ExpSig<Exp> =
NumSig<Exp> & MulSig<Exp>;
repoExp Exp = trait [self: ExpSig<Exp>] => {
mul = Mul (Lit 2) (Lit 3)
};
exp' = new (repoExp @(Eval & Print) ,
evalNum , evalMul , printNum , printMul);
exp'.num.eval —> 6
exp'.num.print —> “2*3”
Background
Intersection type
Merge operator
The CP Language
10
Note: In CP the merge operator is `,` while it’s originally `,,`
Solves the EP
Modular Dependency Injection
Modular Context Evolution
35. Disjoint Intersection Types*
Background
11
Languages with the merge operator may be ambiguous
*Bruno C. d. S. Oliveira, Zhiyuan Shi, and João Alpuim. Disjoint intersection types.
In International Conference on Functional Programming (ICFP), 2016.
36. Disjoint Intersection Types*
Background
11
Languages with the merge operator may be ambiguous
1 ,, 2 has type Int & Int
(1 , , 2) + 3 ⟶ ???
*Bruno C. d. S. Oliveira, Zhiyuan Shi, and João Alpuim. Disjoint intersection types.
In International Conference on Functional Programming (ICFP), 2016.
37. Disjoint Intersection Types*
Background
11
Languages with the merge operator may be ambiguous
1 ,, 2 has type Int & Int
(1 , , 2) + 3 ⟶ ???
Oliveira et al. proposed disjoint intersection types
Reject ambiguous merges with overlapping types
*Bruno C. d. S. Oliveira, Zhiyuan Shi, and João Alpuim. Disjoint intersection types.
In International Conference on Functional Programming (ICFP), 2016.
38. Disjoint Intersection Types*
Background
11
Languages with the merge operator may be ambiguous
1 ,, 2 has type Int & Int
(1 , , 2) + 3 ⟶ ???
Oliveira et al. proposed disjoint intersection types
Reject ambiguous merges with overlapping types
Type is disjoint to type (i.e. )
A B A * B ≐
For all type if and then
C A <: C B <: C C ∼
𝖳
𝗈
𝗉
*Bruno C. d. S. Oliveira, Zhiyuan Shi, and João Alpuim. Disjoint intersection types.
In International Conference on Functional Programming (ICFP), 2016.
39. Disjoint Intersection Types*
Background
11
Languages with the merge operator may be ambiguous
1 ,, 2 has type Int & Int
(1 , , 2) + 3 ⟶ ???
Oliveira et al. proposed disjoint intersection types
Reject ambiguous merges with overlapping types
Type is disjoint to type (i.e. )
A B A * B ≐
For all type if and then
C A <: C B <: C C ∼
𝖳
𝗈
𝗉
Type equivalence
*Bruno C. d. S. Oliveira, Zhiyuan Shi, and João Alpuim. Disjoint intersection types.
In International Conference on Functional Programming (ICFP), 2016.
40. Disjoint Intersection Types*
Background
11
Languages with the merge operator may be ambiguous
1 ,, 2 has type Int & Int
(1 , , 2) + 3 ⟶ ???
Oliveira et al. proposed disjoint intersection types
Reject ambiguous merges with overlapping types
Type is disjoint to type (i.e. )
A B A * B ≐
For all type if and then
C A <: C B <: C C ∼
𝖳
𝗈
𝗉
Type equivalence
Int is the common supertype of Int itself
*Bruno C. d. S. Oliveira, Zhiyuan Shi, and João Alpuim. Disjoint intersection types.
In International Conference on Functional Programming (ICFP), 2016.
41. Disjoint Intersection Types*
Background
11
Languages with the merge operator may be ambiguous
1 ,, 2 has type Int & Int
(1 , , 2) + 3 ⟶ ???
Oliveira et al. proposed disjoint intersection types
Reject ambiguous merges with overlapping types
Type is disjoint to type (i.e. )
A B A * B ≐
For all type if and then
C A <: C B <: C C ∼
𝖳
𝗈
𝗉
Type equivalence
Int is the common supertype of Int itself
Int * Int, therefore 1 ,, 2 is rejected
*Bruno C. d. S. Oliveira, Zhiyuan Shi, and João Alpuim. Disjoint intersection types.
In International Conference on Functional Programming (ICFP), 2016.
42. 12
Motivation
The Calculus - CP’s Foundation
𝖥
+
i
A polymorphic calculus with disjoint intersection types and a merge operator
43. 13
Motivation
The Calculus - CP’s Foundation
𝖥
+
i
A polymorphic calculus with disjoint intersection types and a merge operator
44. 13
Motivation
The Calculus - CP’s Foundation
𝖥
+
i
A polymorphic calculus with disjoint intersection types and a merge operator
The current formulation of
𝖥
+
i
based on an elaboration semantics
45. 13
Motivation
The Calculus - CP’s Foundation
𝖥
+
i
A polymorphic calculus with disjoint intersection types and a merge operator
The current formulation of
𝖥
+
i
• Lack of impredicative polymorphism
• Lack of recursion
its coherence proof causes…
based on an elaboration semantics
46. 13
Motivation
The Calculus - CP’s Foundation
𝖥
+
i
A polymorphic calculus with disjoint intersection types and a merge operator
The current formulation of
𝖥
+
i
• Lack of impredicative polymorphism
• Lack of recursion
While CP allows the creation of
objects with polymorphic methods
its coherence proof causes…
based on an elaboration semantics
47. 14
Motivation
The Calculus - CP’s Foundation
𝖥
+
i
The current formulation of
𝖥
+
i
• Lack of impredicative polymorphism
• Lack of recursion
its coherence proof causes…
based on an elaboration semantics While CP’s elaboration of traits…
↝
A polymorphic calculus with disjoint intersection types and a merge operator
48. 15
Motivation
The Calculus - CP’s Foundation
𝖥
+
i
The current formulation of
𝖥
+
i
its coherence proof causes…
based on an elaboration semantics While CP’s elaboration of traits…
↝
A polymorphic calculus with disjoint intersection types and a merge operator
• Lack of impredicative polymorphism
• Lack of recursion
49. 16
Motivation
The Calculus - CP’s Foundation
𝖥
+
i
The current formulation of
𝖥
+
i
• Di
ff
erence in evaluation strategies
its coherence proof causes…
based on an elaboration semantics
While call-by-value will diverge in…
• CP assumed call-by-name
• is call-by-value
𝖥
+
i
A polymorphic calculus with disjoint intersection types and a merge operator
Note: CP is implemented as call-by-need
• Lack of impredicative polymorphism
• Lack of recursion
50. 17
Motivation
The Calculus - CP’s Foundation
𝖥
+
i
The current formulation of
𝖥
+
i
• Di
ff
erence in evaluation strategies
its coherence proof causes…
based on an elaboration semantics
• CP assumed call-by-name
• is call-by-value
𝖥
+
i
}The gap between theory & practice
A polymorphic calculus with disjoint intersection types and a merge operator
Note: CP is implemented as call-by-need
• Lack of impredicative polymorphism
• Lack of recursion
51. 18
Our Contribution
The Calculus - CP’s Foundation
𝖥
+
i
The new formulation of
𝖥
+
i
its determinism proof is simple
based on a direct Type-Directed Operational Semantics*
• CP assumed call-by-name
• is call-by-name
𝖥
+
i
}The gap between theory & practice
• Lack of impredicative polymorphism
• Lack of recursion
• Di
ff
erence in evaluation strategies
A polymorphic calculus with disjoint intersection types and a merge operator
Note: CP is implemented as call-by-need
*Xuejing Huang and Bruno C. d. S. Oliveira. A type-directed operational semantics for a calculus with a merge operator.
In 34th European Conference on Object-Oriented Programming (ECOOP 2020),
volume 166 of Leibniz International Proceedings in Informatics (LIPIcs), pages 26:1–26:32.
52. 18
Our Contribution
The Calculus - CP’s Foundation
𝖥
+
i
The new formulation of
𝖥
+
i
its determinism proof is simple
based on a direct Type-Directed Operational Semantics*
• CP assumed call-by-name
• is call-by-name
𝖥
+
i
}The gap between theory & practice
• Lack of impredicative polymorphism
• Lack of recursion
• Di
ff
erence in evaluation strategies
A polymorphic calculus with disjoint intersection types and a merge operator
Note: CP is implemented as call-by-need
*Xuejing Huang and Bruno C. d. S. Oliveira. A type-directed operational semantics for a calculus with a merge operator.
In 34th European Conference on Object-Oriented Programming (ECOOP 2020),
volume 166 of Leibniz International Proceedings in Informatics (LIPIcs), pages 26:1–26:32.
53. 18
Our Contribution
The Calculus - CP’s Foundation
𝖥
+
i
The new formulation of
𝖥
+
i
its determinism proof is simple
based on a direct Type-Directed Operational Semantics*
• CP assumed call-by-name
• is call-by-name
𝖥
+
i
}The gap between theory & practice
• Lack of impredicative polymorphism
• Lack of recursion
• Di
ff
erence in evaluation strategies
A polymorphic calculus with disjoint intersection types and a merge operator
Note: CP is implemented as call-by-need
*Xuejing Huang and Bruno C. d. S. Oliveira. A type-directed operational semantics for a calculus with a merge operator.
In 34th European Conference on Object-Oriented Programming (ECOOP 2020),
volume 166 of Leibniz International Proceedings in Informatics (LIPIcs), pages 26:1–26:32.
54. 18
Our Contribution
The Calculus - CP’s Foundation
𝖥
+
i
The new formulation of
𝖥
+
i
its determinism proof is simple
based on a direct Type-Directed Operational Semantics*
• CP assumed call-by-name
• is call-by-name
𝖥
+
i
}The gap between theory & practice
• Lack of impredicative polymorphism
• Lack of recursion
• Di
ff
erence in evaluation strategies
A polymorphic calculus with disjoint intersection types and a merge operator
Note: CP is implemented as call-by-need
*Xuejing Huang and Bruno C. d. S. Oliveira. A type-directed operational semantics for a calculus with a merge operator.
In 34th European Conference on Object-Oriented Programming (ECOOP 2020),
volume 166 of Leibniz International Proceedings in Informatics (LIPIcs), pages 26:1–26:32.
55. 18
Our Contribution
The Calculus - CP’s Foundation
𝖥
+
i
The new formulation of
𝖥
+
i
its determinism proof is simple
based on a direct Type-Directed Operational Semantics*
• CP assumed call-by-name
• is call-by-name
𝖥
+
i
}The gap between theory & practice
• Lack of impredicative polymorphism
• Lack of recursion
• Di
ff
erence in evaluation strategies
A polymorphic calculus with disjoint intersection types and a merge operator
Note: CP is implemented as call-by-need
*Xuejing Huang and Bruno C. d. S. Oliveira. A type-directed operational semantics for a calculus with a merge operator.
In 34th European Conference on Object-Oriented Programming (ECOOP 2020),
volume 166 of Leibniz International Proceedings in Informatics (LIPIcs), pages 26:1–26:32.
56. The Calculus
𝖥
+
i
Example
19
type LitSig<Exp> = { Lit: Int -> Exp };
type Eval = { eval: Int };
type Print = { print: String };
evalLit = trait implements LigSig<Eval> => {
(Lit n).eval = n;
}
printLit = trait implements LigSig<Print> => {
(Lit n).print = toString n;
}
repoLit Exp = trait [self: LitSig<Exp>] => {
num = Lit ((1+1) , true);
};
(new repoLit @(Eval & Print) , evalLit , printLit).num
57. The Calculus
𝖥
+
i
Example
19
type LitSig<Exp> = { Lit: Int -> Exp };
type Eval = { eval: Int };
type Print = { print: String };
evalLit = trait implements LigSig<Eval> => {
(Lit n).eval = n;
}
printLit = trait implements LigSig<Print> => {
(Lit n).print = toString n;
}
repoLit Exp = trait [self: LitSig<Exp>] => {
num = Lit ((1+1) , true);
};
(new repoLit @(Eval & Print) , evalLit , printLit).num
92. Thanks!
More in the paper…
24
• Artifact
• Algorithmic subtyping with polymorphic types
• Enhanced subtyping and disjointness
• More CP examples
• Self-contained presentation of
𝖥
+
i
93. Thanks!
More in the paper…
25
• Artifact
• Algorithmic subtyping with polymorphic types
• Enhanced subtyping and disjointness
• More CP examples
• Self-contained presentation of
𝖥
+
i
*Xuejing Huang, Jinxu Zhao, and Bruno C. d. S. Oliveira.
Taming the merge operator. Journal of Functional Programming, 31:e28, 2021.
94. Thanks!
More in the paper…
25
• Artifact
• Algorithmic subtyping with polymorphic types
Based on splittable types*
• Enhanced subtyping and disjointness
• More CP examples
• Self-contained presentation of
𝖥
+
i
*Xuejing Huang, Jinxu Zhao, and Bruno C. d. S. Oliveira.
Taming the merge operator. Journal of Functional Programming, 31:e28, 2021.
95. Thanks!
More in the paper…
25
• Artifact
• Algorithmic subtyping with polymorphic types
Based on splittable types*
• Enhanced subtyping and disjointness
More types equivalent to Top
• More CP examples
• Self-contained presentation of
𝖥
+
i
*Xuejing Huang, Jinxu Zhao, and Bruno C. d. S. Oliveira.
Taming the merge operator. Journal of Functional Programming, 31:e28, 2021.
96. Thanks!
More in the paper…
25
• Artifact
is type sound, formalized in the Coq theorem prover
𝖥
+
i
• Algorithmic subtyping with polymorphic types
Based on splittable types*
• Enhanced subtyping and disjointness
More types equivalent to Top
• More CP examples
• Self-contained presentation of
𝖥
+
i
A PureScript implementation of CP on top of
𝖥
+
i
*Xuejing Huang, Jinxu Zhao, and Bruno C. d. S. Oliveira.
Taming the merge operator. Journal of Functional Programming, 31:e28, 2021.