Header menu logo FSharp.Data

BinderScriptNotebook

WorldBank Provider

The World Bank is an international organization that provides financial and technical assistance to developing countries around the world. As one of the activities, the World Bank also collects development indicators and other data about countries in the world. The data catalog contains over 8,000 indicators that can be programmatically accessed.

The WorldBank Type Provider makes the WorldBank data easily accessible to F# programs and scripts in a type-safe manner. This article provides an introduction.

Introducing the provider

The following example initializes a connection to the WorldBank using the GetDataContext method and then retrieves the percentage of population who attend universities in the UK:

open FSharp.Data

let data = WorldBankData.GetDataContext()

data.Countries.``United Kingdom``.Indicators.``Gross capital formation (% of GDP)``
|> Seq.maxBy fst
val data: FSharp.Data.WorldBankData.ServiceTypes.WorldBankDataService
val it: int * float = (2022, 18.60201024)

When generating the data context, the WorldBank Type Provider retrieves the list of all countries known to the WorldBank and the list of all supported indicators. Both of these dimensions are provided as properties, so you can use autocomplete to easily discover various data sources. Most of the indicators use longer names, so we need to wrap the name in \``.

The result of the Gross capital formation (% of GDP) property is a sequence with values for different years. Using Seq.maxBy fst we get the most recent available value.

Using World Bank data asynchronously

If you need to download large amounts of data or run the operation without blocking the caller, then you probably want to use F# asynchronous workflows to perform the operation. The FSharp.Data package also provides the WorldBankDataProvider type which takes a number of static parameters. If the Asynchronous parameter is set to true then the type provider generates all operations as asynchronous:

type WorldBank = WorldBankDataProvider<"World Development Indicators", Asynchronous=true>
WorldBank.GetDataContext()

The above snippet specified "World Development Indicators" as the name of the data source (a collection of commonly available indicators) and it set the optional argument Asynchronous to true. As a result, properties such as Gross capital formation (% of GDP) will now have a type Async<(int * int)[]> meaning that they represent an asynchronous computation that can be started and will eventually produce the data.

Downloading data in parallel

To demonstrate the asynchronous version of the type provider, let's write code that downloads the university enrollment data about a number of countries in parallel. We first create a data context and then define an array with some countries we want to process:

let wb = WorldBank.GetDataContext()

// Create a list of countries to process
let countries =
    [| wb.Countries.``Arab World``
       wb.Countries.``European Union``
       wb.Countries.Australia
       wb.Countries.Brazil
       wb.Countries.Canada
       wb.Countries.Chile
       wb.Countries.Czechia
       wb.Countries.Denmark
       wb.Countries.France
       wb.Countries.Greece
       wb.Countries.``Low income``
       wb.Countries.``High income``
       wb.Countries.``United Kingdom``
       wb.Countries.``United States`` |]

To download the information in parallel, we can create a list of asynchronous computations, compose them using Async.Parallel and then run the (single) obtained computation to perform all the downloads:

[ for c in countries -> c.Indicators.``Gross capital formation (% of GDP)`` ]
|> Async.Parallel
|> Async.RunSynchronously
val it: Runtime.WorldBank.Indicator array =
  [|Gross capital formation (% of GDP); Gross capital formation (% of GDP);
    Gross capital formation (% of GDP); Gross capital formation (% of GDP);
    Gross capital formation (% of GDP); Gross capital formation (% of GDP);
    Gross capital formation (% of GDP); Gross capital formation (% of GDP);
    Gross capital formation (% of GDP); Gross capital formation (% of GDP);
    Gross capital formation (% of GDP); Gross capital formation (% of GDP);
    Gross capital formation (% of GDP); Gross capital formation (% of GDP)|]

Related articles

Multiple items
namespace FSharp

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

--------------------
namespace Microsoft.FSharp.Data
val data: WorldBankData.ServiceTypes.WorldBankDataService
type WorldBankData = static member GetDataContext: unit -> WorldBankDataService nested type ServiceTypes
WorldBankData.GetDataContext() : WorldBankData.ServiceTypes.WorldBankDataService
property WorldBankData.ServiceTypes.WorldBankDataService.Countries: WorldBankData.ServiceTypes.Countries with get
module Seq from Microsoft.FSharp.Collections
val maxBy: projection: ('T -> 'U) -> source: 'T seq -> 'T (requires comparison)
val fst: tuple: ('T1 * 'T2) -> 'T1
type WorldBank = WorldBankDataProvider<...>
type WorldBankDataProvider
<summary>Typed representation of WorldBank data with additional configuration parameters. See http://www.worldbank.org for terms and conditions.</summary> <param name='Sources'>The World Bank data sources to include, separated by semicolons. Defaults to <c>World Development Indicators;Global Financial Development</c>. If an empty string is specified, includes all data sources.</param> <param name='Asynchronous'>Generate asynchronous calls. Defaults to false.</param>
WorldBankDataProvider<...>.GetDataContext() : WorldBankDataProvider<...>.ServiceTypes.WorldBankDataService
val wb: WorldBankDataProvider<...>.ServiceTypes.WorldBankDataService
val countries: WorldBankDataProvider<...>.ServiceTypes.Country array
property WorldBankDataProvider<...>.ServiceTypes.WorldBankDataService.Countries: WorldBankDataProvider<...>.ServiceTypes.Countries with get
property WorldBankDataProvider<...>.ServiceTypes.Countries.Australia: WorldBankDataProvider<...>.ServiceTypes.Country with get
The data for country 'Australia'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Brazil: WorldBankDataProvider<...>.ServiceTypes.Country with get
The data for country 'Brazil'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Canada: WorldBankDataProvider<...>.ServiceTypes.Country with get
The data for country 'Canada'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Chile: WorldBankDataProvider<...>.ServiceTypes.Country with get
The data for country 'Chile'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Czechia: WorldBankDataProvider<...>.ServiceTypes.Country with get
The data for country 'Czechia'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Denmark: WorldBankDataProvider<...>.ServiceTypes.Country with get
The data for country 'Denmark'
property WorldBankDataProvider<...>.ServiceTypes.Countries.France: WorldBankDataProvider<...>.ServiceTypes.Country with get
The data for country 'France'
property WorldBankDataProvider<...>.ServiceTypes.Countries.Greece: WorldBankDataProvider<...>.ServiceTypes.Country with get
The data for country 'Greece'
val c: WorldBankDataProvider<...>.ServiceTypes.Country
property WorldBankDataProvider<...>.ServiceTypes.Country.Indicators: WorldBankDataProvider<...>.ServiceTypes.Indicators with get
<summary>The indicators for the country</summary>
Multiple items
type Async = static member AsBeginEnd: computation: ('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit) static member AwaitEvent: event: IEvent<'Del,'T> * ?cancelAction: (unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate) static member AwaitIAsyncResult: iar: IAsyncResult * ?millisecondsTimeout: int -> Async<bool> static member AwaitTask: task: Task<'T> -> Async<'T> + 1 overload static member AwaitWaitHandle: waitHandle: WaitHandle * ?millisecondsTimeout: int -> Async<bool> static member CancelDefaultToken: unit -> unit static member Catch: computation: Async<'T> -> Async<Choice<'T,exn>> static member Choice: computations: Async<'T option> seq -> Async<'T option> static member FromBeginEnd: beginAction: (AsyncCallback * obj -> IAsyncResult) * endAction: (IAsyncResult -> 'T) * ?cancelAction: (unit -> unit) -> Async<'T> + 3 overloads static member FromContinuations: callback: (('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T> ...

--------------------
type Async<'T>
static member Async.Parallel: computations: Async<'T> seq -> Async<'T array>
static member Async.Parallel: computations: Async<'T> seq * ?maxDegreeOfParallelism: int -> Async<'T array>
static member Async.RunSynchronously: computation: Async<'T> * ?timeout: int * ?cancellationToken: System.Threading.CancellationToken -> 'T

Type something to start searching.