Browse Source

We have proper lists!

David Peter 1 year ago
parent
commit
5ed16a0638
3 changed files with 35 additions and 28 deletions
  1. 18 7
      examples/list_tests.nbt
  2. 13 19
      numbat/modules/core/lists.nbt
  3. 4 2
      numbat/src/typechecker/constraints.rs

+ 18 - 7
examples/list_tests.nbt

@@ -1,14 +1,25 @@
 let xs = [1, 2, 3]
 
-#assert(len([]) == 0)
-# assert(len(xs) == 3)
+assert(len([]) == 0)
+assert(len(xs) == 3)
 
-# assert(head(xs) == 1)
-# assert(tail(xs) == [2, 3])
+assert(head(xs) == 1)
+assert(tail(xs) == [2, 3])
 
+assert(sequence(0) == [])
 assert(sequence(5) == [0, 1, 2, 3, 4])
+
+fn const_5(x) = 5
 assert(generate(3, const_5) == [5, 5, 5])
-assert(map(inc, [1, 2, 3]) == [2, 3, 4])
-assert(reverse([1, 2, 3]) == [3, 2, 1])
-assert(foldl(add, 0, [1, 2, 3, 4, 5]) == 15)
+
+
+fn inc(x) = x + 1
+assert(map(inc, xs) == [2, 3, 4])
+
+assert(reverse([]) == [])
+assert(reverse(xs) == [3, 2, 1])
+
+assert(sum([1, 2, 3, 4, 5]) == 15)
+
+fn mul(x, y) = x * y
 assert(foldl(mul, 1, [1, 2, 3, 4, 5]) == 120)

+ 13 - 19
numbat/modules/core/lists.nbt

@@ -7,41 +7,35 @@ fn cons<A>(x: A, xs: List<A>) -> List<A>
 
 fn is_empty<A>(xs: List<A>) -> Bool = xs == []
 
-# We definitely want to make the following functions generic, but this is not yet possible.
-
-fn generate(n: Scalar, f: Fn[() -> Scalar]) -> List<Scalar> =
+fn generate<A>(n: Scalar, f: Fn[() -> A]) -> List<A> =
   if n == 0
     then []
     else cons(f(), generate(n - 1, f))
 
-fn map(f: Fn[(Scalar) -> Scalar], xs: List<Scalar>) -> List<Scalar> =
-  if len(xs) == 0
+fn map<A, B>(f: Fn[(A) -> B], xs: List<A>) -> List<B> =
+  if is_empty(xs)
     then []
     else cons(f(head(xs)), map(f, tail(xs)))
 
-fn cons_end(xs: List<Scalar>, x: Scalar) -> List<Scalar> =
+fn cons_end<A>(xs: List<A>, x: A) -> List<A> =
   if is_empty(xs)
     then [x]
     else cons(head(xs), cons_end(tail(xs), x))
 
-fn reverse(xs: List<Scalar>) -> List<Scalar> =
-  if len(xs) == 0
+fn reverse<A>(xs: List<A>) -> List<A> =
+  if is_empty(xs)
     then []
     else cons_end(reverse(tail(xs)), head(xs))
 
 fn sequence(n: Scalar) -> List<Scalar> =
-  if n == 1
-    then [0]
+  if n == 0
+    then []
     else cons_end(sequence(n - 1), n - 1)
 
-fn foldl(f: Fn[(Scalar, Scalar) -> Scalar], acc: Scalar, xs: List<Scalar>) -> Scalar =
-  if len(xs) == 1
-    then f(acc, head(xs))
+fn foldl<A, B>(f: Fn[(A, B) -> A], acc: A, xs: List<B>) -> A =
+  if is_empty(xs)
+    then acc
     else foldl(f, f(acc, head(xs)), tail(xs))
 
-fn const_5() -> Scalar = 5
-
-fn inc(x: Scalar) -> Scalar = x + 1
-
-fn add(x: Scalar, y: Scalar) -> Scalar = x + y
-fn mul(x: Scalar, y: Scalar) -> Scalar = x * y
+fn add(x, y) = x + y # TODO
+fn sum<A>(xs: List<A>) -> A = foldl(add, 0, xs)

+ 4 - 2
numbat/src/typechecker/constraints.rs

@@ -254,6 +254,7 @@ impl Constraint {
                 )))
             }
             Constraint::Equal(s, Type::TVar(x)) if !s.contains(x) => {
+                // TODO: merge with branch above
                 debug!(
                     "  (3) SOLVING: {s} ~ {x} with substitution {x} := {s}",
                     s = s,
@@ -310,9 +311,10 @@ impl Constraint {
             Constraint::Equal(Type::Dimension(d1), Type::Dimension(d2)) => {
                 let d_result = d1.divide(d2);
                 debug!(
-                    "  (7) SOLVING: {} ~ {} with new constraint d_result = Scalar",
+                    "  (7) SOLVING: {} ~ {} with new constraint {} = Scalar",
                     d1.pretty_print(),
-                    d2.pretty_print()
+                    d2.pretty_print(),
+                    d_result.pretty_print()
                 );
                 Some(Satisfied::with_new_constraints(vec![
                     Constraint::EqualScalar(d_result),