Jam don't add like that

APL, 44 bytes


APL's + distributes over arrays as well, but in a different enough manner that this can't really be used. However, there is a built-in depth function ().


  • 1=≡⍺⍵:⍺+⍵: if the depths of are both zero (and therefore the depth of ⍺ ⍵ is 1), add them.
  • ∆←|≡¨⍺⍵: take the absolute of the depth of both and and store them in . ( gives a negative value if not all elements have the same depth.)
  • =/∆: if they have the same depth:
    • ↓↑⍺⍵: pad the shortest array with zeroes to match the longer array
    • ⊃∇¨/: distribute the function over both arrays
  • </∆: if the depth of is less than that of :
    • ⍺∘∇¨⍵: bind and then map over
  • ⍵∇⍺: if nothing else (so is deeper than ), swap the arguments and try again.

Mathematica, 122 bytes


Defines a recursive function f which computes the sum. Making use of Mathematica's pattern matching, this function is made up of four separate definitions:


If the depth of x is greater than that of y, swap the arguments so that we only have to handle distribution in one direction (which we can do, since addition is commutative).


If the depth of x is less thann that of y, replace each value # in y with f[x,#], which takes care of the distribution for arguments of unequal depth.


Otherwise, if one argument is a list (which implies that the other also is a list, since we know they have the same depth), we put both arguments in a list, pad them to the same length with PadRight[..., Automatic] (which simply fills up a ragged array with zeros to make it rectangular), and then use MapThread to apply f to corresponding pairs from the two lists.

And finally, the base case:


If none of the other patterns match, we must be trying to add two numbers, so we just do that.

Haskell, 150 bytes

data L=S Int|V{v::[L]}
d(V z)=1+maximum(d<$>S 0:z);d _=0
S x!S y=S$x+y
x!y|d x<d y=V$(x!)<$>v y|d x>d y=y!x|1<2=V$v x#v y


The first line defines an algebraic data type L, which is either a Scalar (containing an Int) or a Vector (containing a list of Ls, accessed using a record getter v, which is a partial function L → [L].)

The second line defines the depth function: the depth of a Vector is one plus its maximum depth. I prepend S 0 to the values in the vector, so that depth [] == 1 + maximum [depth (S 0)] == 1. The depth of “anything else” (a scalar) is 0.

The third line defines the base case for ! (the addition function): the sum of scalars is simply a scalar.

The fifth line defines a variant of zipWith (!) that just picks elements from the longest list when one of them is empty.

The fourth line is split in three cases:

x!y | d x<d y = V$(x!)<$>v y
    | d x>d y = y!x
    | True    = V$v x#v y
  • If the depth of x is strictly less than the depth of y, map (x!) over the elements of y. (The use of v is guaranteed to be valid, as d(y) ≥ 1.)

  • If the depth of x is strictly greater, flip the arguments and restart.

  • If their depths are equal, zip the arguments together with (!). (The use of v is guaranteed to be valid, as the case d(x) = d(y) = 0 was handled as a base case.)

Test cases

instance Show L where
  show (S x) = show x
  show (V x) = show x

lArg = V [S 1, V [S 2, V [S 3, V [S 4]]]]
rArg = V [S 10, V [S 20]]

Then show (lArg ! rArg) == "[[11,[21]],[[12,[22]],[13,[24]]]]".