F# type providers are amazing - they can be used for a wide range of things such as reading data in CSV, JSON and XML formats, accessing SQL databases, reading data exposed by international organizations such as the World Bank, interoperating with the R langauge, but also fun things like playing adventure games in your editor.
Sadly, writing type providers is not very easy. You have to use fairly complicated
provided types API and
learn how to use advanced F#
<@@ "code" + "quotations" @@>.
Wouldn't it be nice if you could create type providers without all this complexity?
The REST provider is a project that does exactly this. The idea is simple:
You write a simple REST service that provides endpoints representing the different provided types and returns information about the types in a simple JSON format. You can write the service in F# or anything else you fancy.
You pass the URL for your service to REST type provider by writing
RestProvider<"http://myservice/provider">and the REST provider takes care of doing all the magic that is needed to provide types.
You can find a number of samples in the REST provider repository and you can read more about the protocol and other fun examples in the detailed documentation (see links below), but just to give you a taste - the following calls the minimal sample provider that returns information about cities:
1: 2: 3: 4: 5: 6: 7:
When you clone the repository, you can start the server that hosts sample providers by running
build RunServers. This will start a lightweight Suave server that runs on port 10042 which
is then called by the
RestProvider. In the above example, we look at population of two cities
using a type representing a city with members
New York. The members return value
of another type representing an indicator which has a member
The server that is behind the above type provider is very simple. The REST provider first makes a request to the base URL passed in the type provider argument:
1: 2: 3: 4:
The response returns a list of members with
name (the name of the property). The
field specifies the type of the result - here, we are just saying that the result is another
provided type that can be obtained by making a relative request to
represents an information that will be used later once we try to get the data - you can think
/city as a type and
trace values (
"NYC") as values of that type.
When you type
cities.London, the provider requests type for the city:
1: 2: 3: 4:
As before, the
/city type has a number of members (that will appear as properties). They both
add a value to
trace to track what data we want to get at the end. The
returns field now says
that the result is a primitive type
int. It also specifies the endpoint for accessing the data.
The endpoint is called when you evaluate
POST /minimal/data with body
The provider accumulates
trace values that are generated by the individual members that we
encounter as we "dot through" the provided types, concatenates it using
& and passes it as the
body to the
/data endpoint. For primitive
int types, the endpoint just returns the number.
This project is still very experimental and everything is likely going to change, including the protocol that is used for the communication between the REST server and the type provider. There are many things that the provider should, but does not support yet (say, providing methods) and the protocol is too simplistic. If you have thoughts, please comment on GitHub issues!
This documentation contains some more information about the current version of the protocol and also a few examples for creating providers (see the menu on the right for the latests links). You can also browse the Suave sources directory on GitHub, which contains sample data providers written using Suave.
The project is hosted on GitHub where you can report issues, fork the project and submit pull requests. If you're adding a new public API, please also consider adding samples that can be turned into a documentation.
The library is available under the Apache 2.0 license, which allows modification and redistribution for both commercial and non-commercial purposes. For more information see the License file in the GitHub repository.
Full name: Index.cities
Full name: TheGamma.RestProvider
<param name="Source">A thing</param>