4 people like it.

# Finding nearest airplane to a location

Given a location as a float tuple (latitude, longitude) it will return the plane closest nearby as a JsonValue using the OpenSky API. For fun also demonstrating some operator overloading with (-->) between two coordinates. I'm new to these functional languages, so please feel free to update the solution with interesting refactortings and whatnot.

 ``` 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: ``` ``````#r "FSharp.Data.dll" open System open FSharp.Data let (-->) (lat1,lon1) (lat2,lon2) = let deg2rad deg = deg * (Math.PI/180.) let (dLat,dLon) = deg2rad (abs (lat1-lat2)), deg2rad (abs(lon1-lon2)) let a = (sin(dLat / 2.)) * (sin(dLat / 2.)) + (cos(deg2rad(lat1))) * (cos(deg2rad(lat2))) * (sin(dLon/2.)) * (sin(dLon/2.)) 6371. * (2. * (atan2 (sqrt a) (sqrt (1. - a)))) let nearestPlane location : JsonValue = let url = "https://opensky-network.org/api/states/all" let valueJSON = JsonValue.Load(url) let n = Array.length (valueJSON.["states"].AsArray()) let rec findPlane i recordPlane recordDistance = if i = n then recordPlane else let state = valueJSON.["states"].[i] if state.[5] = JsonValue.Null || state.[6] = JsonValue.Null then findPlane (i+1) recordPlane recordDistance else let distance = location --> (state.[6].AsFloat(), state.[5].AsFloat()) if recordDistance > distance then findPlane (i+1) state distance else findPlane (i+1) recordPlane recordDistance findPlane 0 (JsonValue.Null) (1e99) //Examples: nearestPlane (51.507351, -0.127758) //-- London nearestPlane (48.860731, 2.342342) //-- Paris nearestPlane (35.708628, 139.731891) //-- Tokyo ``````
namespace System
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Data

--------------------
namespace Microsoft.FSharp.Data
val lat1 : float
val lon1 : float
val lat2 : float
val lon2 : float
val deg2rad : (float -> float)
val deg : float
type Math =
static val PI : float
static val E : float
static member Abs : value:sbyte -> sbyte + 6 overloads
static member Acos : d:float -> float
static member Asin : d:float -> float
static member Atan : d:float -> float
static member Atan2 : y:float * x:float -> float
static member BigMul : a:int * b:int -> int64
static member Ceiling : d:decimal -> decimal + 1 overload
static member Cos : d:float -> float
...

Full name: System.Math
field Math.PI = 3.14159265359
val dLat : float
val dLon : float
val abs : value:'T -> 'T (requires member Abs)

Full name: Microsoft.FSharp.Core.Operators.abs
val a : float
val sin : value:'T -> 'T (requires member Sin)

Full name: Microsoft.FSharp.Core.Operators.sin
val cos : value:'T -> 'T (requires member Cos)

Full name: Microsoft.FSharp.Core.Operators.cos
val atan2 : y:'T1 -> x:'T1 -> 'T2 (requires member Atan2)

Full name: Microsoft.FSharp.Core.Operators.atan2
val sqrt : value:'T -> 'U (requires member Sqrt)

Full name: Microsoft.FSharp.Core.Operators.sqrt
val nearestPlane : float * float -> JsonValue

Full name: Script.nearestPlane
val location : float * float
type JsonValue =
| String of string
| Number of decimal
| Float of float
| Record of properties: (string * JsonValue) []
| Array of elements: JsonValue []
| Boolean of bool
| Null
member Request : uri:string * ?httpMethod:string * ?headers:seq<string * string> -> HttpResponse
member RequestAsync : uri:string * ?httpMethod:string * ?headers:seq<string * string> -> Async<HttpResponse>
override ToString : unit -> string
member ToString : saveOptions:JsonSaveOptions -> string
member WriteTo : w:TextWriter * saveOptions:JsonSaveOptions -> unit
static member AsyncLoad : uri:string * ?cultureInfo:CultureInfo -> Async<JsonValue>
static member private JsonStringEncodeTo : w:TextWriter -> value:string -> unit
static member Load : uri:string * ?cultureInfo:CultureInfo -> JsonValue
static member Load : reader:TextReader * ?cultureInfo:CultureInfo -> JsonValue
static member Load : stream:Stream * ?cultureInfo:CultureInfo -> JsonValue
static member Parse : text:string * ?cultureInfo:CultureInfo -> JsonValue
static member ParseMultiple : text:string * ?cultureInfo:CultureInfo -> seq<JsonValue>
static member ParseSample : text:string * ?cultureInfo:CultureInfo -> JsonValue

Full name: FSharp.Data.JsonValue
val url : string
val valueJSON : JsonValue
static member JsonValue.Load : uri:string * ?cultureInfo:Globalization.CultureInfo -> JsonValue
static member JsonValue.Load : reader:IO.TextReader * ?cultureInfo:Globalization.CultureInfo -> JsonValue
static member JsonValue.Load : stream:IO.Stream * ?cultureInfo:Globalization.CultureInfo -> JsonValue
val n : int
type Array =
member Clone : unit -> obj
member CopyTo : array:Array * index:int -> unit + 1 overload
member GetEnumerator : unit -> IEnumerator
member GetLength : dimension:int -> int
member GetLongLength : dimension:int -> int64
member GetLowerBound : dimension:int -> int
member GetUpperBound : dimension:int -> int
member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
member Initialize : unit -> unit
member IsFixedSize : bool
...

Full name: System.Array
val length : array:'T [] -> int

Full name: Microsoft.FSharp.Collections.Array.length
val findPlane : (int -> JsonValue -> float -> JsonValue)
val i : int
val recordPlane : JsonValue
val recordDistance : float
val state : JsonValue
union case JsonValue.Null: JsonValue
val distance : float

### More information

 Link: http://fssnip.net/7Vk Posted: 4 years ago Author: Johan Irvall Tags: distance , json , operator overloading