Skip to content

Commit

Permalink
type: Add Num
Browse files Browse the repository at this point in the history
  • Loading branch information
slotThe committed Mar 15, 2024
1 parent 1a3a7be commit 6cb2310
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 23 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,9 @@ $ cargo metadata --format-version=1 | rq '.packages | map .name'

``` agda
(+) : JSON → JSON → JSON -- Also works for string concatenation
(-) : JSONJSONJSON
(*) : JSONJSONJSON
(/) : JSONJSONJSON
(-) : NumNumNum
(*) : NumNumNum
(/) : NumNumNum
```

- Comparisons:
Expand All @@ -185,10 +185,10 @@ $ cargo metadata --format-version=1 | rq '.packages | map .name'
``` agda
(=) : JSON → JSON → JSON
(!=) : JSON → JSON → JSON
(<) : JSONJSONJSON
(<=) : JSONJSONJSON
(>) : JSONJSONJSON
(>=) : JSONJSONJSON
(<) : NumNumNum
(<=) : NumNumNum
(>) : NumNumNum
(>=) : NumNumNum
```

- Higher order functions:
Expand Down
39 changes: 27 additions & 12 deletions src/eval/stdlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub static STDLIB_TYPES: LazyLock<BTreeMap<String, Type>> = LazyLock::new(|| {
});

pub static STDLIB: LazyLock<BTreeMap<Builtin, StdFun>> = LazyLock::new(|| {
use Type::JSON;
use Type::*;

BTreeMap::from([
mk_fun!(
Expand Down Expand Up @@ -149,7 +149,16 @@ pub static STDLIB: LazyLock<BTreeMap<Builtin, StdFun>> = LazyLock::new(|| {
),
mk_fun!(
Builtin::Map, // (a → b) → [a] → [b]
Type::arr(Type::arr(JSON, JSON), Type::arr(JSON, JSON)),
Type::forall(
"a",
Type::forall(
"b",
Type::arr(
Type::arr(Type::var("a"), Type::var("b")),
Type::arr(JSON, JSON)
)
)
),
Blocks::new()
.fancy("map f xs")
.plain("applies")
Expand All @@ -174,9 +183,15 @@ pub static STDLIB: LazyLock<BTreeMap<Builtin, StdFun>> = LazyLock::new(|| {
),
mk_fun!(
Builtin::Foldl, // (b → a → b) → b → [a] → b
Type::arr(
Type::arr(JSON, Type::arr(JSON, JSON)),
Type::arr(JSON, Type::arr(JSON, JSON)),
Type::forall(
"a",
Type::forall(
"b",
Type::arr(
Type::arr(Type::var("b"), Type::arr(Type::var("a"), Type::var("b"))),
Type::arr(Type::var("b"), Type::arr(JSON, Type::var("b"))),
)
)
),
Blocks::new()
.plain("Left-associative fold over an array or (values of an) object; e.g.,")
Expand All @@ -189,18 +204,18 @@ pub static STDLIB: LazyLock<BTreeMap<Builtin, StdFun>> = LazyLock::new(|| {
),
mk_fun!(
Builtin::Sub,
Type::arr(JSON, Type::arr(JSON, JSON)),
Type::arr(Num, Type::arr(Num, Num)),
Blocks::to_plain("Subtract two numbers."),
),
mk_fun!(
Builtin::Mul,
Type::arr(JSON, Type::arr(JSON, JSON)),
Type::arr(Num, Type::arr(Num, Num)),
Blocks::to_plain("Multiply two numbers."),
"·"
),
mk_fun!(
Builtin::Div,
Type::arr(JSON, Type::arr(JSON, JSON)),
Type::arr(Num, Type::arr(Num, Num)),
Blocks::to_plain(
"Divide two numbers. No guarantees if the denominator is zero—the world might \
explode.",
Expand All @@ -221,7 +236,7 @@ pub static STDLIB: LazyLock<BTreeMap<Builtin, StdFun>> = LazyLock::new(|| {
),
mk_fun!(
Builtin::Le,
Type::arr(JSON, Type::arr(JSON, JSON)),
Type::arr(Num, Type::arr(Num, Num)),
Blocks::new()
.fancy("e < e'")
.plain("checks whether")
Expand All @@ -231,7 +246,7 @@ pub static STDLIB: LazyLock<BTreeMap<Builtin, StdFun>> = LazyLock::new(|| {
),
mk_fun!(
Builtin::Leq,
Type::arr(JSON, Type::arr(JSON, JSON)),
Type::arr(Num, Type::arr(Num, Num)),
Blocks::new()
.fancy("e ≤ e'")
.plain("checks whether")
Expand All @@ -242,7 +257,7 @@ pub static STDLIB: LazyLock<BTreeMap<Builtin, StdFun>> = LazyLock::new(|| {
),
mk_fun!(
Builtin::Ge,
Type::arr(JSON, Type::arr(JSON, JSON)),
Type::arr(Num, Type::arr(Num, Num)),
Blocks::new()
.fancy("e > e'")
.plain("checks whether")
Expand All @@ -252,7 +267,7 @@ pub static STDLIB: LazyLock<BTreeMap<Builtin, StdFun>> = LazyLock::new(|| {
),
mk_fun!(
Builtin::Geq,
Type::arr(JSON, Type::arr(JSON, JSON)),
Type::arr(Num, Type::arr(Num, Num)),
Blocks::new()
.fancy("e ≥ e'")
.plain("checks whether")
Expand Down
11 changes: 9 additions & 2 deletions src/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ impl Exist {
#[derive(PartialEq, Eq, Debug, Clone, PartialOrd, Ord)]
#[allow(clippy::upper_case_acronyms)]
pub enum Type {
/// A number
Num,
/// The JSON black hole
JSON,
/// A type variable α
Var(String),
Expand All @@ -64,6 +67,7 @@ pub enum Type {
impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Num => write!(f, "Num"),
Self::JSON => write!(f, "JSON"),
Self::Var(α) => write!(f, "{α}"),
Self::Arr(box Self::Arr(t11, t12), t2) => write!(f, "({t11} → {t12}) → {t2}"),
Expand All @@ -88,7 +92,7 @@ impl Type {
/// Substitute the type variable α with type B in A.
pub fn subst(self, to: Self, from: &str) -> Self {
match self {
Self::JSON | Self::Exist(_) => self.clone(),
Self::Num | Self::JSON | Self::Exist(_) => self.clone(),
Self::Var(ref α) => {
if α == from {
to.clone()
Expand All @@ -110,7 +114,7 @@ impl Type {
/// Substitute type C for B in A.
pub fn subst_type(self, to: &Self, from: &Self) -> Self {
match self {
Self::JSON | Self::Var(_) | Self::Exist(_) => {
Self::Num | Self::JSON | Self::Var(_) | Self::Exist(_) => {
if self == *from {
to.clone()
} else {
Expand Down Expand Up @@ -151,6 +155,7 @@ impl Type {
#[derive(PartialEq, Eq, Debug, Clone)]
#[allow(clippy::upper_case_acronyms)]
pub enum Monotype {
Num,
JSON,
/// A type variable α
Var(String),
Expand All @@ -164,6 +169,7 @@ impl Monotype {
/// Convert a [Monotype] to a (poly)[Type].
pub fn to_poly(&self) -> Type {
match self {
Self::Num => Type::Num,
Self::JSON => Type::JSON,
Self::Var(α) => Type::Var(α.clone()),
Self::Exist(α̂) => Type::Exist(*α̂),
Expand All @@ -180,6 +186,7 @@ impl Type {
pub fn to_mono(&self) -> Option<Monotype> {
match self {
Self::Forall(_, _) => None,
Self::Num => Some(Monotype::Num),
Self::JSON => Some(Monotype::JSON),
Self::Var(α) => Some(Monotype::Var(α.clone())),
Self::Exist(α̂) => Some(Monotype::Exist(*α̂)),
Expand Down
8 changes: 6 additions & 2 deletions src/type/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//! The article is readily available [on the arXiv](https://arxiv.org/abs/1306.6032).
use super::{context::{Item, State}, error::{TResult, TypeCheckError}, Exist, Monotype, Type};
use crate::expr::{self, Expr};
use crate::expr::{self, Const, Expr};

impl Type {
/// A.well_formed_under(Γ) ≡ Γ ⊢ A
Expand All @@ -18,6 +18,7 @@ impl Type {
fn well_formed_under(&self, ctx: &[Item]) -> TResult<()> {
match self {
// UnitWF
Type::Num => Ok(()),
Type::JSON => Ok(()),
// UvarWF
Type::Var(α) => {
Expand Down Expand Up @@ -65,9 +66,11 @@ impl Type {
},
// <:JSON ≡ <:Unit
(Type::JSON, Type::JSON) => Ok(()),
// A number is a subtype of a JSON object.
(Type::Num, Type::Num | Type::JSON) => Ok(()),
// <:→
(Type::Arr(a1, a2), Type::Arr(b1, b2)) => {
b1.subtype_of(state, a1)?;
b1.subtype_of(state, a1)?; /* Contravariant! */
// See Note [Apply]
a2.apply_ctx(&state.ctx)
.subtype_of(state, &b2.apply_ctx(&state.ctx))
Expand Down Expand Up @@ -221,6 +224,7 @@ impl Expr {
// println!("infer; ctx: {:?} e: {:?}", state.ctx, self);
match self {
// 1l⇒
Expr::Const(Const::Num(_)) => Ok(Type::Num),
Expr::Const(_) | Expr::Arr(_) | Expr::Obj(_) => Ok(Type::JSON),
Expr::Builtin(b) => expr::var(b.show()).synth(state),
// Var
Expand Down

0 comments on commit 6cb2310

Please sign in to comment.