Units of Measure in F#: Part Three, Generic Units

In the first two articles in this series, we saw how to declare base and derived units, introduce constants with units, define our own conversion functions, and have F# check the units for us.

But what if we're writing code that doesn't care what units it is working in? That's the subject of today's article.

Let's start simple. What is the type of fun x -> x*x? Well, multiplication is overloaded, so F# defaults to integers:

image

But if we annotate the argument, we can define squaring for all kinds of floats (hovering over the last of these to show its type):

image

This looks painful! What if we don't tell F# what the units are, using the underscore notation to say "find me its units"?

image

F# has inferred a generic unit type for squaring. The notation 'u looks like a type parameter, but is in fact a unit-of-measure parameter that can be instantiated at any units. Let's use it on masses, lengths and speeds:

image

F# can infer generic unit-of-measure types with type annotations required only to resolve overloading. Here are some simple examples, tested out in F# Interactive:

image

Here's one that requires a bit of head-scratching to understand:

image 

Returning to reality, suppose we want to sum the elements of a list. In true functional style, we use one of the fold operators.

image

Oops - we don't seem to have a nice generic type! The reason is simple: unless units are specified, constants, including zero, are assumed to have no units, i.e. to be dimensionless. So instead, let's give 0.0 some units, but not tell F# what they are, by writing 0.0<_>:

image 

That's better!

Now we can go wild and write all sorts of statistical stuff.

image

And here are the beautiful types that are inferred for these functions:

image

Summing up: we've seen how to write code that is generic (a.k.a. as polymorphic) in units-of-measure.

Next time , we'll write types that are generic in units-of-measure. This makes the feature extensible: if floats with units aren't what you want, just define your own types!

Comments

  • Anonymous
    September 05, 2008
    PingBack from http://www.alvinashcraft.com/2008/09/05/dew-drop-september-5-2008/
  • Anonymous
    September 24, 2008
    First, let me remind you that in my new ongoing quest to read source code to be a better developer ,
  • Anonymous
    September 25, 2008
    The comment has been removed
  • Anonymous
    October 03, 2008
    Andrew,I do wonder if the 4th part of the series will be coming soon. I am using this feature for a new research project and have found it impossible to be able to. My problem is defining 3D vectors/points that are generic with respect to the units of measures. I have had significant trouble in particular with operator overloading. Any help would be fantastic!
  • Anonymous
    October 11, 2008
    F# es un lenguaje funcional, creado por Microsoft. Implementado bajo el soporte de .NET CLR, es un lenguaje
  • Anonymous
    November 28, 2008
    NASA气象卫星意外坠落说明,计量单位绝非小事。为编程语言添加对计量单位的支持可以很大程度上避免这样的错误,编程任务也变得更有趣。F#提供了对计量单位的静态检查,并且封装了国际单位制的各个单位和物理常量,另外我们也可以定义自己的单位;在单位之间进行换算也很简单;此外F#还支持计量单位的泛型。作为对NASA气象卫星的纪念,本文最后给出了一个模拟太阳系的例子 :)
  • Anonymous
    January 11, 2009
    Kean over at AutoDesk (think AutoCAD etc.) is running an F# programming contest ! I've included his post
  • Anonymous
    February 10, 2009
    Ostatnio ponowiłem wysiłki do opanowania nowych języków z rodziny MS w tym także implementacji znanych
  • Anonymous
    February 15, 2009
    Ostatnio ponowiłem wysiłki do opanowania nowych języków z rodziny MS w tym także implementacji znanych
  • Anonymous
    May 07, 2012
    n my case units of measure, especially for weight-quantities and currencies and combinations of them, are in a database. There could be MT, KG, LBS, but also custom units such as Bags (for coffee), Barrels (for oil), and all other kinds of unusual units. We store conversion factors between them as well. Can we use the F# units with such dynamically configurable units? thanks, Joseph