Elliptic Fourier series are a good example to kick the tires on array programming systems; J and Python, however, are both dynamically typed.

A modern statically approach makes things significantly easier on the programmer; here I will use my Apple language, which aspires to the interactivity and conciseness of the APL family.

One has a principled yet safe version of Haskell's zip or J's " (re-rank on a dyadic verb):

> :ty \f.\x.\y. f`x y ((a → (b → c)) → (Arr (i `Cons` Nil) a → (Arr (i `Cons` Nil) b → Arr (i `Cons` Nil) c)))

This avoids the pitfalls of zip-ing different-length lists (one cannot write eqList = zipWith (==) in Haskell) and avoids deferring failures to runtime as in J.

One can inspect the type signature of cons:

> :ty (<|) (a → (Arr (i `Cons` Nil) a → Arr ((i + 1) `Cons` Nil) a))

There is a safe last:

> :ty }. (Arr ((i + 1) `Cons` Nil) a → a)

These work together:

> :ty \x.\xs. }.(x<|xs) (b → (Arr (i `Cons` Nil) b → b))

I believe this combination of interactivity and type inference in array programming will be quite productive.

To address the elliptic Fourier series, we focus on the offsets \(A_0\) and \(C_0\). This is straightforward to express with mathematical notation:

\( \displaystyle A_0 = \frac{1}{T} \sum_{p=1}^{K} \left(\frac{\Delta x_p}{2\Delta t_p}(t_p^2-t_{p-1}^2) + \xi_p(t_p-t_{p-1}) \right) \\ \displaystyle C_0 = \frac{1}{T} \sum_{p=1}^{K} \left(\frac{\Delta y_p}{2\Delta t_p}(t_p^2-t_{p-1}^2) + \delta_p(t_p-t_{p-1}) \right)\)

where

\( \xi_p = \displaystyle\sum_{j=1}^{p-1}\Delta x_j - \frac{\Delta x_p}{\Delta t_p}\sum_{j=1}^{p-1}\Delta t_j \\ \delta_p = \displaystyle\sum_{j=1}^{p-1}\Delta y_j - \frac{\Delta y_p}{\Delta t_p}\sum_{j=1}^{p-1}\Delta t_j \)

In Apple:

λxs.λys. { sum ⇐ [(+)/1 0 x] ; dxs ⟜ (-)\~xs; dys ⟜ (-)\~ys ; dts ⟜ [√(x^2+y^2)]dxs dys ; pxs ← (+)Λ 0 dxs; pys ← (+)Λ 0 dys; pts ⟜ (+)Λ 0 dts ; dtss ⟜ 0<|(-)\~((^2)'1 pts) ; T ⟜}.pts ; 𝜉 ← (-)\pxs ((*)`((%)`dxs dts) pts) ; 𝛿 ← (-)`pys ((*)`((%)`dys dts) pts) ; A ← ((sum ((*)`((%)`dxs dts) dtss))%2 + (sum ((*)`𝜉 dts)))%T ; C ← ((sum ((*)`((%)`dys dts) dtss))%2 + (sum ((*)`𝛿 dts)))%T ; (A,C) }

This all typechecks! So we can be sure that there will not be off-by-one errors.