Skip to content

Instantly share code, notes, and snippets.

@brendanzab
Last active March 25, 2025 11:43
Show Gist options
  • Save brendanzab/285c31f1c5dc9da954cd48c8fbee47b7 to your computer and use it in GitHub Desktop.
Save brendanzab/285c31f1c5dc9da954cd48c8fbee47b7 to your computer and use it in GitHub Desktop.
Set interface as a codata type in Polarity (see: https://polarity-lang.github.io)
data Bool { T, F }
data Nat { Z, S(n: Nat) }
def (n1: Nat).eq(n2: Nat): Bool {
Z => n2.match {
Z => T,
S(_) => F,
},
S(n1) => n2.match {
Z => F,
S(n2) => n1.eq(n2),
},
}
data Eq(a: Type, x y: a) {
Refl(a: Type, x: a): Eq(a, x, x)
}
// Set interface from Section 3 of “On Understanding Data Abstraction, Revisited”
// by William R. Cook https://www.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf
codata Set {
.is_empty: Bool,
.contains(i: Nat): Bool,
.insert(i: Nat): Set,
.union(r: Set): Set,
}
codef Empty: Set {
.is_empty => T,
.contains(_) => F,
.insert(i) => Insert(Empty, i),
.union(s) => s,
}
#[transparent]
let Insert(s: Set, n: Nat): Set {
s.contains(n).match {
T => s,
F => Insert'(s, n),
}
}
// NOTE (2025-03-25): Polarity does not currently allow local comatches to use
// self parameters. Instead we lift this to the top-level.
codef Insert'(s: Set, n: Nat): Set {
.is_empty => F,
.contains(i) =>
i.eq(n).match {
T => T,
F => s.contains(i),
},
.insert(i) => Insert(Insert'(s, n), i),
.union(r) => Union(Insert'(s, n), r),
}
codef Union(s1 s2: Set): Set {
.is_empty => F,
.contains(i) =>
s1.contains(i).match {
T => T,
F => s2.contains(i),
},
.insert(i) => Insert(Union(s1, s2), i),
.union(r) => Union(Union(s1, s2), r),
}
codef Full : Set {
.is_empty => F,
.contains(_) => T,
.insert(_) => Full,
.union(_) => Full,
}
// Tests
let paper_example : Eq(Bool, Empty.insert(3).union(Empty.insert(1)).insert(5).contains(4), F) {
Refl(Bool, F)
}
@brendanzab
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment