diff --git a/arr.sml b/arr.sml
index 4fd419abdf3437cf899e11d5added8c22fb79218..bf5f6bcbb612c28c03169809e0736a4135c94864 100644
--- a/arr.sml
+++ b/arr.sml
@@ -7,7 +7,8 @@              | FM of arr -> arr
              | FD of (arr * arr) -> arr
              | STOP
 and     arr  = Lf of atom (* arrays as binary trees - SML doesn't allow arbitrarily nested lists *)
-             | Nd of arr * arr
+             | Nd of arr * arr (* (val, next) *)
+             | Bx of arr * arr (* (shape, arr) *)
 with
 exception Domain;
 exception BadStop;
@@ -17,14 +18,23 @@ fun Fun0(f) = Lf(FN(f));
 fun Fun1(f) = Lf(FM(f));
 fun Fun2(f) = Lf(FD(f));
 fun Stop() = Lf(STOP);
-fun Array [] = Stop()
-  | Array (x::xs) = Nd(x,Array(xs));
-fun str(Lf(STOP)) = "!!" (* TODO: box-drawing characters might be nice in the future *)
+fun Array([]) = Stop()
+  | Array(x::xs) = Nd(x,Array(xs)); (* TODO: automatically box? *)
+fun unbox(Bx(s,a)) = a
+  | unbox(x) = x;
+fun tally(Lf(STOP)) = 0w0
+  | tally(Lf(a:atom)) = 0w1
+  | tally(Nd(x,y)) = 0w1 + tally y
+  | tally(Bx(s,a)) = tally (unbox a);
+fun Box(a:arr) = Bx(Array([Word (tally a)]),a); (* TODO: Unbox? *)
+fun shape(Bx(s,a)) = Box(s);
+fun str(Lf(STOP)) = "" (* TODO: box-drawing characters might be nice in the future *)
   | str(Lf(N(x))) = Word8.fmt StringCvt.HEX x
   | str(Lf(FN(x))) = "(Nilad)" (* TODO: would be nice to get actual function names *)
   | str(Lf(FM(x))) = "(Monad)"
   | str(Lf(FD(x))) = "(Dyad)"
-  | str(Nd(x,y)) = "[" ^ str(x) ^ " " ^ str(y) ^ "]" (* FIXME: clearer nesting would be nice *)
+  | str(Nd(x,y)) = str(x) ^ " " ^ str(y)
+  | str(Bx(s,a)) = "[ " ^ str(a) ^ "]"
 (* TODO: higher-order functions *)
 fun apply0(f) = raise NYI; (* TODO - what if it generates a whole array? *)
 fun apply1(f,Lf(STOP)) = Lf(STOP) (* traverse the array tree, applying f to each leaf in turn *)
@@ -32,13 +42,14 @@   | apply1(f,Lf(N(x))) = Lf(N(f(x)))
   | apply1(f,Nd(x,y)) = Nd(apply1(f,x),apply1(f,y));
 fun apply2(f,x,y) = raise NYI; (* TODO *)
 fun append(x,a) = Nd(x,a);
-fun addD(x,Lf(STOP)) = x (* dyadic add *)
+(* fun addD(x,Lf(STOP)) = x (* dyadic add *)
   | addD(Lf(N(x)),Lf(N(y))) = Lf(N(x+y))
-  | addD(Nd(x,xs),Lf(N(y))) = Nd(Lf(N(x+y)),add(xs,Lf(N(y)))) (* FIXME: doesn't work because x might be a Nd - need to do cases for Nd(Lf(N(x)),xs) &c. *)
+  | addD(Nd(x,xs),Lf(N(y))) = Nd(Lf(N(x+y)),add(xs,Lf(N(y)))) (* FIXME: doesn't
+  work because x might be a Nd - need to do cases for Nd(Lf(N(x)),xs) &c. *) 
   | addD(Lf(N(x)),Nd(y,ys)) = Nd(Lf(N(x+y)),add(Lf(N(x)),ys))
-  | addD(Nd(x,xs),Nd(y,ys)) = raise NYI; (* TODO *)
+  | addD(Nd(x,xs),Nd(y,ys)) = raise NYI; (* TODO *) *)
 end;
 
 (* Test data *)
-val a = Array([Word(0w2),Word(0w3),Word(0w4),Word(0w5)]);
-val b = Array([Word(0w2),Array([Word(0w3),Word(0w4)]),Word(0w5)]);
+val a = Box(Array([Word(0w2),Word(0w3),Word(0w4),Word(0w5)]));
+val b = Box(Array([Word(0w2),Box(Array([Word(0w3),Word(0w4)])),Word(0w5)]));
