Introduction to F# with Xamarin

Guest Blogger

rachel-reeseRachel Reese (@RachelReese) is a long-time software engineer and math geek who recently relocated to Nashville, TN to work at Firefly Logic. Rachel is an ASPInsider and an F# MVP. You can catch her at Xamarin Evolve 2014, where you can learn from industry leaders and Xamarin expertsto advance your projects and career.

This blog post is part of our continuing celebration of F# Week at Xamarin! Celebrate by getting your own F# t-shirt!

Why F#? Let’s first dig into a few of my favorite reasons to consider F# for your next Xamarin project: type inference, units of measure, type providers, as well as the ever-crucial clarity and conciseness of code.

Type Inference People often underestimate the benefits of type inference, but the ability to clear out the type definitions from code and concentrate on the code itself, instead of all the clutter around the declaration, is tremendous. Consider this example (from here, via here):

C#:

    public static Tree<KeyValuePair<A, bool>> DiffTree<A>(Tree<A> tree, Tree<A> tree2)
    {
        return XFoldTree((A x, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> l, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> r, Tree<A> t) => (Tree<A> t2) =>
            Node(new KeyValuePair<A, bool>(t2.Data, object.ReferenceEquals(t, t2)),
                 l(t2.Left), r(t2.Right)),
            x => y => null, tree)(tree2);
    }

The equivalent F# is much easier on the eyes. The code itself might still be incomprehensible, but it is at least not drowning in required type definitions. It’s no longer necessary to filter through all the extra information before trying to understand what’s happening.

let DiffTree(tree,tree2) =
    XFoldTree (fun x l r t t2 ->
        let (Node(x2,l2,r2)) = t2
        Node((x2,t===t2), l l2, r r2)) (fun _ _ -> Leaf) tree tree2

For more information on type inference, see the F# for Fun and Profit website. There are some fabulous examples of how it works, and how to troubleshoot the errors that sometimes show up.

Units of Measure Units of measure are types that allow one to add unit information to a numeric type in F#. Once a value is tagged with a unit type, it can only be combined with other values that have that same unit. For example, if we want to track distances and times, it’s possible to create:

[<Measure>] type s
[<Measure>] type m

Then, when we define a new value, we can easily associate our new unit with it:

let time = 30<s>
let distance = 10<m>

The compiler will error if we try to add the two values, but it is possible to divide them:

let velocity = distance/time

If we hover over this declaration, the tooltip for this value will show:

val velocity : int<m/s>

All scientific computing will benefit from enforcing units (game physics!) but it doesn’t have to be exclusively the domain of science. Think about using pixel, USD, or Fahrenheit, among others!

It’s also possible to use generic units of measure in a function. For example, we’d like to calculate a perimeter, given some distances. We can declare the function like so:

let perimeter = (x:int,<'distance>) (y:int<'distance>) = 2*x + 2*y

In this manner, we’re able to utilize one function for many different units of measure. As long as the units for a single given call are the same, the code will compile. However, the compiler will still throw an error if we try to call perimeter with two different units. To wit:

// Compiler error: The unit of measure 'ft' does not match the unit of measure 'm'
let p_1 = perimeter 10<m> 4<m>
let p_2 = perimeter 2<ft> 3<m>

Type Providers Type providers are a mechanism that allows F# code to access typed information from external data sources with no code generation, all in just a few lines of code. They are a revolution in data access! F# was the first enterprise-grade language to have type providers, and is still the only .NET language to have them. So, if we want to use a type provider in our Xamarin project, we’ll need to use F#!

There are many, many type providers available, but I’ll concentrate on two that are especially useful with Xamarin projects today – the SQLProvider and the Freebase Provider.

SQLProvider

The SQLProvider provides access to MS SQL Server, SQLite, PostgreSQL, Oracle, MySQL, ODBC, and MS Access databases. Since SQLite is a tremendously common database to hook up with both iOS and Android applications, let’s take a look at what’s required to use the SQLProvider type provider to connect to a SQLite database in an F# Xamarin project!

First, we declare a type. We’ll need to change this to include the connection string, as well as the path to the mono.sqlite.dll.

type sql = SqlDataProvider

At this point, we’re ready to go. To show off the SQLite provider, let’s build a quick port of the Xamarin Tasky app (see original here). We’ll need to create just a couple of functions for our data layer: GetIncompleteTasks, AddTask, UpdateTask, and DeleteTask. However, first we need to get the data context:

let ctx = sql.GetDataContext ()

Every time we type `ctx`, we’ll get code completion on the remaining pieces:

2014-07-01_1414

As well as tooltips, which show that the information coming back from SQLite is fully typed:

2014-07-01_1415

Once we have set up the data context, creating the methods we need is as easy as pie. Let’s declare a type for the return data, to use in our queries:

type task = { Description : string; mutable Complete : bool; }

Then, to return the incomplete tasks, we use the familiar query syntax:

let GetIncompleteTasks () =
    query { for data in ctx.``[main].[tasks]`` do
                where (data.complete = 0L)
                select {Description=data.task; Complete = false}}
            |> Sql.toList

This returns an F# list of tasks, where complete is false. That’s it. No messy ORMs to contend with, no long data access libraries to futz with; we only need a database connection and a query. Adding a task is just as easy, we need to create a new task, update the two fields (“<-” is the F# assignment operator), and finally, submit our updates.

let AddTask description =
    let newTask = ctx.``[main].[tasks]``.Create()
    newTask.task <- description
    newTask.complete <- 0L
    ctx.SubmitUpdates()

Freebase

The Freebase.com web site describes itself as a community-curated database. They currently have a list of nearly 44 million topics, and over 2.5 billion facts. Connecting our app in to all their data is simple, with the Freebase type provider! We merely need to get the context, and start querying.

The Freebase database is especially exciting because the data is returned with additional units of measure. In the example above, when the results are returned, and in the tooltips, we can see that the particle charge is shown in coulombs!

2014-07-01_1422

As with all type providers, the Freebase provider also has code completion into the structure of our data source. It frees us up to explore the data!

2014-07-01_1423

Keep an eye out on the Xamarin Blog for Part 2 of Getting Started with Xamarin and F#, where I’ll discuss using F# to build amazing cross-platform, native apps.

 

0 comments

Discussion is closed.

Feedback usabilla icon