# Computing the distance between two locations from coordinates in F#

The following code returns the distance between to locations based on each point’s longitude and latitude. The distance returned is relative to Earth’s radius. To get the distance in miles, multiply by 3960. To get the distance in kilometers, multiply by 6373.

Latitude is measured in degrees north of the equator; southern locations have negative latitude. Similarly, longitude is measured in degrees east of the Prime Meridian. A location 10° west of the Prime Meridian, for example, could be expressed as either 350° east or as -10° east.

The following F# implementation comes from Kevin Hazzard. See also Python implementation.

```[<Measure>] type radian
[<Measure>] type degree
[<Measure>] type km
[<Measure>] type mi
type LatLong = { Lat : float<degree>; Long : float<degree> }

// a unit-of-measure (UoM) generic F# function based on
// John D. Cook's Python version - https://www.johndcook.com
// a UoM generic suface distance
let SphereSurfaceDistance[<Measure>] 't>
(radius : float<'t>) (loc1 : LatLong) (loc2 : LatLong) =
// Convert latitude and longitude to
let degrees_to_radians (d : float<degree>) =

// phi = 90 - latitude (coded F# pipeline style)
let phi1 = (90.0<degree> - loc1.Lat) |> degrees_to_radians
let phi2 = (90.0<degree> - loc2.Lat) |> degrees_to_radians

// theta = longitude (coded F# function call style)

// Compute spherical distance from spherical coordinates.

// For two locations in spherical coordinates
// (1, theta, phi) and (1, theta, phi)
// cosine( arc length ) =
//    sin phi sin phi' cos(theta-theta') + cos phi cos phi'
// distance = rho * arc length

radius * acos(sin(float(phi1)) * sin(float(phi2)) *
cos(float(theta1 - theta2)) +
cos(float(phi1)) * cos(float(phi2)))

// instantiate Earth-relative functions in km and miles
let SurfaceDistanceOnEarthKm = SphereSurfaceDistance 6371.0<km>
let SurfaceDistanceOnEarthMile = SphereSurfaceDistance 3959.0<mi>

let test1_SurfaceDistanceOnEarthMile =
let richmond = { Lat = 37.542979<degree>; Long = -77.469092<degree> }
let saopaulo = { Lat = -23.548943<degree>; Long = -46.638818<degree> }

// distance between Richmond, Virginia USA and S o Paulo, Brazil

let tst_dist = SurfaceDistanceOnEarthMile richmond saopaulo
let std_dist = 4677.562<mi>
let delta = abs (tst_dist - std_dist) / std_dist
// assert delta from standard < 1/4 of a percent
delta < 0.0025

let test1_SurfaceDistanceOnEarthKm =
let richmond = { Lat = 37.542979<degree>; Long = -77.469092<degree> }
let saopaulo = { Lat = -23.548943<degree>; Long = -46.638818<degree> }

// distance between Richmond, Virginia USA and S o Paulo, Brazil
let tst_dist = SurfaceDistanceOnEarthKm richmond saopaulo
let std_dist = 7527.806<km>
let delta = abs (tst_dist - std_dist) / std_dist
// assert delta from standard < 1/4 of a percent
delta < 0.0025

```

The code above assumes the earth is perfectly spherical. For a discussion of how accurate this assumption is, see my blog post on the shape of the Earth.

The algorithm used to calculate distances is described in detail here.

A web page to calculate the distance between to cities based on longitude and latitude is available here.

This code is in the public domain. Do whatever you want with it, no strings attached. 