First, some definitions:

In [3]:

```
[<Measure>] type kg
[<Measure>] type m
[<Measure>] type s
[<Measure>] type N = kg * m / s^2
let G = 6.674e-11<N * m^2 / kg^2>
```

Out[3]:

In [4]:

```
let grav_force (m1:float< kg>) (r:float<m>) (m2:float<kg>) =
if r = 0.<m> then 0.<N>
else ((m1 * m2) * G) / (r * r)
```

Out[4]:

Returning to our function `grav_force`

, when we put it into F# we got the type:

`val grav_force ∈ m1∈float<kg> ⟹ r∈float<m> ⟹ m2∈float<kg> ⟹ float<N>`

So everything looks good, it takes a mass (such as Earth) and returns a function that takes a distance (e.g. at the surface) which itself returns a function: one from masses (your mass) to Forces (your weight). This function is in fact the definition of a (*scalar*) gravitational field but more on that later. We can *specialize* the function and get earth's field.

In [5]:

```
let earth_mass = 5.96e24<kg>
let earth_rad = 6.37e6<m>
let earth_grav = grav_force earth_mass
```

Out[5]:

`earth_grav`

) or we can compute the mass of an object at a particular distance by passing in a distance *and* a mass. For example, noticing that `N = kg m/s²`

, we can compute Earth's accelaration at surface simply by passing in *1kg* and the Earth's radius for a value of 9.802877992 N (which is just m/s² for this case). But we can do more interesting things with curried functions. We can flip the field equation to compute the gravitational force at a list of distances from earth's surface (a bit more flexible than how physics is typically taught isn't it):

In [6]:

```
let flip f a b = f b a
let flipped_field = flip earth_grav 1.<kg>
```

Out[6]:

In [181]:

```
[for dist in 0.0<m>..1e5<m>..1e6<m> -> 6.37e6<m> + dist] |> List.map flipped_field
```

Out[181]:

Below you can look at the gravitational acceleration on the surface of the moon and Mars. The moon has a mere acceleration of 1.62 m/s² and Mars is only just over 2x that—it is for this reason that many are concerned over the health effects (on skeletomuscular integrity) of an extended mission to Mars.

Additionally, we can look at the Earth/Moon system. The Moon and the Earth both exert a force of $2 \times10^{20}\,N$ on each other. Both are forever falling towards each other, with the condition that—on the odd chance that—if ever they should meet, things would not end well for both of them. A tragic love story if ever there was one.

In [6]:

```
let mass_moon = 7.3459e22<kg>
let mass_mars = 6.41693e23<kg>
let rad_moon = 1737.5<m> * 1000.
let radius_mars = 3386.<m> * 1000.
let mean_moon_dist = 3.85e8<m>
grav_force mass_moon rad_moon 1.<kg> ,
grav_force mass_mars radius_mars 1.<kg> ,
grav_force earth_mass mean_moon_dist mass_moon
```

Out[6]:

In [8]:

```
let pois = [|"~Low Earth Orbit Min", 160.<m>
"~Low Earth Orbit Max", 2000.<m>
"GEO Synch" , 40000.<m>
"GPS" , 20350.<m>
"ISS Avg" , 382.5<m>
"Hubble Space Telescope", 595.<m>|]
let gs = pois |> Array.map (snd >> ( * ) 1000. >> (+) earth_rad >> flipped_field)
Array.zip pois gs
|> Array.sortBy snd
|> Array.map (fun ((l,n),g) -> [|l; string n ; string g|])
|> tohtmlTable ["Location"; "Distance in km"; "g"]
```

Out[8]:

There is an art, it says, or rather, a knack to flying. The knack lies in learning how to throw yourself at the ground and miss. Pick a nice day, [The Hitchhiker's Guide to the Galaxy] suggests, and try it.

The first part is easy. All it requires is simply the ability to throw yourself forward with all your weight, and the willingness not to mind that it's going to hurt.

That is, it's going to hurt if you fail to miss the ground. Most people fail to miss the ground, and if they are really trying properly, the likelihood is that they will fail to miss it fairly hard.

Clearly, it is the second part, the missing, which presents the difficulties..."

--Douglas Adams

At this point, I can't help but note that I've veered a bit far afield. The original intention of this piece was to connect curried functions from functional programs to fields in physics and yet, here I am talking about how falling is flying with no pesky forces in the way. Nonetheless, I hope the above has been an effective demonstration of the advantage of a computational approach to learning topics commonly thought of as challenging (there'll be more such demonstrations in the below). In reality, much of the difficulty is incidental instead of necessary: for the student, it is grappling with inconsistent and often unmotivated notation, as well as plain general unfamiliarity or counter-intuitiveness and for the teacher: the baggage of being wedded to centuries old tradition of how subjects must be taught. Much pointless complexity arises from the interaction of all those variables.

Right, on topic. The real world has more than just one dimension. Depending on whom you ask, it can be anywhere from 3 or 4 to 11 to 26 or more or less. Most real world (classical) problems settle on 3 however. And here, again we see the advantage of a computational approach. It takes only a few lines to generalize our methodology to vectors (and though it's general to N-dimensions, only for 3—or 2 in a few places—does it really makes sense for the operations we're performing).

Expand vector helpers

In [11]:

```
let grav_field (m1:float<kg>) (r:float<m> []) (m2:float<kg>) =
let mag = vec_mag r * 1.<m>
let scale = (-G * m1 * m2) / cube mag
r |> Array.map (( * ) scale)
```

Out[11]:

In [89]:

```
grav_field earth_mass [|1.<m>; 0.<m>; earth_rad|] 68.0<kg> ,
grav_field earth_mass [|1.<m>; 12.<m>; earth_rad|] 1.0<kg>
```

Out[89]:

The functional way of viewing fields is that they are curried functions; through partial application they can either return more specialized functions or with enough inputs, (e.g.) a vector of forces. For example, the common static field is a function that takes an object of some appropriate type (say, Coulombs or Kg) and returns a function that accepts position vectors which itself returns a function that takes objects (of the same type) and maps them to forces. So by applying (e.g.) a mass, M, to the gravitational field function we specialize to talking about the gravitational field around M. Further specifying a position vector allows us to talk about the force at that distance for various other masses.

In short, fields are really functions. And the way they are used makes them the same as using curried functions with partial application.

*"real-valued quantum random variables correspond to self-adjoint operators affiliated with $\mathcal{A}$ [a von Neumann algebra on operators over a Hilbert Space], as postulated in quantum mechanics*". One can also apply the notion of Observables to classical mechanics, and there also, they are functions that smell like random variables. And so, measurement can be thought of as an evaluation and hence, computation. Working backwards and having everything fit this way is really nice.

Quantum Field Theory further muddies our picture because there, people talk about fields as if they were a real thing and particles as excitations in this field. If fields are actually curried functions with specializations obtained through partial application, what does it mean for a function to be excited? However, it's worth remembering that at the bottom of it all, there is a computation that's carried out; a fluctuating field suggests that there's a computation unfolding—in other words, evaluating the field gives different values over time. This is also suggestive of another curiosity—fields in physics are actually two different things. There is the field as function and then there is the underlying computation that is eventually evaluated (or calculation or phenomenon*, the 'real' thing).

In the classical world, measurement yields simple things like vectors, in the quantum realm we get probability distributions. There exist computations whose outputs are also probability distributions: probabilistic programs. Putting all these together, when a physicist says fields are interacting or oscillating, we can think of a probabilistic program (on noncommuting random variables) whose inputs are curried functions and, in some sense, mutually recursive with other 'fields', all of which unfolds some computation (over time).

**If for whatever reason, you do not like the idea of a computable reality, at the least our only interface with it through testable predictions must be.*

Expand Visualize Fields

Out[13]:

*Constant*! By looking at the types, the similarity between the two fields is really brought into focus (more so than the similarity between the equations IMO) because the ability to specify both fields with a single function really forces one to take notice of the equivalence.

In [17]:

```
[<FunScript.JS>]
let static_field (constant:float<'some_constant>)
(m1:float<'some_quantity>)
(r:float<m> [])
(m2:float<'some_quantity>) =
let mag = vec_mag r * 1.<m>
let scale = (constant * m1 * m2) / cube mag
r |> Array.map (( * ) scale)
```

Out[17]:

*'some_constant * 'some_quantity²/m²*, capturing the inverse square aspect of the relationship. We can then write the gravitational field in terms of static field and all the types work out and the function works as it should:

In [18]:

```
let gravitational_field (m:float<kg>) (r:float<m> []) (m2:float<kg>) = static_field -G m r m2
gravitational_field earth_mass [|10.<m>; 5.<m>;earth_rad|] 1.<kg>
```

Out[18]:

In [19]:

```
[<Measure>] type C
let k = 9e9<N * m ^2 / C^2>
let electric_field (q:float<C>) (r:float<m> []) (q2:float<C>) = static_field k q r q2
electric_field 1.0<C> [| 1.0<m> |] 1.0<C> = [| 9e9<N> |]
```

Out[19]:

In [70]:

```
G,k, log10 (float k) - log10 (float G)
```

Out[70]:

In [252]:

```
//Electrostatic fields
[<FunScript.JS>]
module ElectorstaticFields =
let electric_field (q:float<C>) (r:float<m> []) (q2:float<C>) = static_field k q r q2
let eforce_on_q (r,q) (r', q') = electric_field q (sub r r') q'
let efield_force charge qs = qs |> Array.map (eforce_on_q charge) |> sum_force_vecs
let efield_sum qs r = total_efield_force (r,1.0<C>) qs |> Array.map (flip (/) 1.<C>)
```

Out[252]:

At this point, it's instructive to highlight an example of the unnecessary obtuseness that abounds in physics equations. Given some test charge q, and a set of discrete charges, the electric field felt by q is given by: $$F(r) = q \cdot k \sum\limits_{i=1}^n {q_i\frac{r-r_i}{|r-r_i|^3}}$$

The problem of course, is that the Equation does not make clear that the function $F$ should take a pair of variables: the charge and its vector. It's assumed implicity, and thus one more thing to be confused about. The same function is given by `efield_force`

where the type makes it clear that the field is parameterized by both a position vector *and* a charge.

animate gravity electric and grav of proton negative mass

discrete probability conjugate information being information geometry oscillators,gliders, computation model not reality

In [113]:

```
let mass_inf, c_inf = queryWolfram "mass of proton to kg", queryWolfram "charge of proton in Coulombs"
mass_inf.["Result"], c_inf.["Result"]
```

Out[113]:

In [255]:

```
open ElectorstaticFields
efield_sum charge_density (cm_list [|1.; sqrt 3.|]) //|> Array.map ((*) (-2. |> nano_coulombs))
```

Out[255]:

In [1]:

```
open ElectorstaticFields
[for x in 0.0..9. do
for y in 0.0..9. ->
Array.append [|string x; string y|] (efield_sum charge_density (cm_list [|x; y|]) |> Array.map string)]
|> tohtmlTable []
```

In [160]:

```
[<FunScript.JS>]
let mainc() =
let x,y = 2.,3.
vec_mag [|x;y|],electric_field_sum charge_density (cm_list [|x; y|]) |> vec_mag
let js2 = Compiler.compileWithoutReturn (<@mainc()@>)
js2
```

Out[160]:

Expand Funscript Canvas

In [25]:

```
{Html = html + "<script>" + js + "</script>"}
```

Out[25]: