
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.
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
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.
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.
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[] =
[|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)|]
|
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
<summary>Contains operations for working with values of type <see cref="T:Microsoft.FSharp.Collections.seq`1" />.</summary>
val maxBy: projection: ('T -> 'U) -> source: seq<'T> -> 'T (requires comparison)
<summary>Returns the greatest of all elements of the sequence, compared via Operators.max on the function result.</summary>
<param name="projection">A function to transform items from the input sequence into comparable keys.</param>
<param name="source">The input sequence.</param>
<returns>The largest element of the sequence.</returns>
<exception cref="T:System.ArgumentNullException">Thrown when the input sequence is null.</exception>
<exception cref="T:System.ArgumentException">Thrown when the input sequence is empty.</exception>
<example id="maxby-1"><code lang="fsharp">
let inputs = ["aaa"; "b"; "cccc"]
inputs |> Seq.maxBy (fun s -> s.Length)
</code>
Evaluates to <c>"cccc"</c></example>
<example id="maxby-2"><code lang="fsharp">
let inputs = [ ]
inputs |> Seq.maxBy (fun s -> s.Length)
</code>
Throws <c>System.ArgumentException</c>.
</example>
val fst: tuple: ('T1 * 'T2) -> 'T1
<summary>Return the first element of a tuple, <c>fst (a,b) = a</c>.</summary>
<param name="tuple">The input tuple.</param>
<returns>The first value.</returns>
<example id="fst-example"><code lang="fsharp">
fst ("first", 2) // Evaluates to "first"
</code></example>
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[]
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: seq<Async<'T option>> -> 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>
...
<summary>Holds static members for creating and manipulating asynchronous computations.</summary>
<remarks>
See also <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/asynchronous-workflows">F# Language Guide - Async Workflows</a>.
</remarks>
<category index="1">Async Programming</category>
--------------------
type Async<'T>
<summary>
An asynchronous computation, which, when run, will eventually produce a value of type T, or else raises an exception.
</summary>
<remarks>
This type has no members. Asynchronous computations are normally specified either by using an async expression
or the static methods in the <see cref="T:Microsoft.FSharp.Control.Async" /> type.
See also <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/asynchronous-workflows">F# Language Guide - Async Workflows</a>.
</remarks>
<namespacedoc><summary>
Library functionality for asynchronous programming, events and agents. See also
<a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/asynchronous-workflows">Asynchronous Programming</a>,
<a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/members/events">Events</a> and
<a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/lazy-expressions">Lazy Expressions</a> in the
F# Language Guide.
</summary></namespacedoc>
<category index="1">Async Programming</category>
static member Async.Parallel: computations: seq<Async<'T>> -> Async<'T[]>
static member Async.Parallel: computations: seq<Async<'T>> * ?maxDegreeOfParallelism: int -> Async<'T[]>
static member Async.RunSynchronously: computation: Async<'T> * ?timeout: int * ?cancellationToken: System.Threading.CancellationToken -> 'T