October 31, 2009
Units of measure in F#
The latest version of F# introduces units of measure. Using this feature, you can indicate that a numeric value is in a particular unit – metres, seconds, etc. – and the compiler will track that as part of the data type and validate that units are being converted and compared correctly.
For example, we can declare the following values:
let distance = 1000.0<m>
let time = 400.0<s>
Give these the ol’ Intellisense mouse waggle, and you find that distance has type float<m>, and time has type float<s>. Try to add them together, and you get a tasty compiler error:
let nonsense = distance + time
FS0043: The unit of measure 's' does not match the unit of measure 'm'
But divide them and the compiler recognises that it makes sense, and figures out and tracks the derived unit of measure:
let speed = distance / time
speed has type float<m/s>, and again the compiler enforces that operations on speed are compatibly typed:
let description =
if speed > 10.0<m s^-1> then
"fast"
else
"slow"
Notice that F# supports the Proper Science notation of negative exponents as well as the Way Everybody Really Does It of division notation.
Derived units of measure can have names: the type float<kg m s^-2> is the same as float<N> and values of these types are therefore compatible.
let mass = 1.0<kg>
let accel = 50.0<m/s^2>
let whompiness = mass * accel
let ouch = whompiness > 100.0<N> // compiles
Where do units of measure come from? Well, when a daddy unit of measure and a mommy unit of measure love each other very much… but we’ve already talked about derived units of measure. In fact, there are no units of measure built into the F# language or core library. So either you have to define the units you need using the MeasureAttribute:
[<Measure>] type m
or you can import a bunch of standard SI units (basic units like the metre, kilogram and second, and derived units like newtons) from the F# Power Pack DLL:
// after referencing FSharp.PowerPack.dll
open Microsoft.FSharp.Math.SI
The Power Pack also includes a bunch of physical constants:
open Microsoft.FSharp.Math
let description =
if speed < PhysicalConstants.c then
"it's science"
else
"it's science... fiction!"
Naturally, these are all declared with the correct units of measure so efforts to compare Planck’s constant to the speed of light will meet with ignominious failure. To work around this, tell your boss you need $370bn for a new particle accelerator.
To be clear, F# doesn’t assign any actual semantics to units. For example, if you declare imperial units (because if it was good enough for the Babbage Engine, it’s good enough for the CLR, by Jove):
[<Measure>] type ft
F# won’t let you combine feet with metres. It has no way of knowing that ft is a length measure, or how it would convert to metres. However you can of course create conversion functions for your units:
let feetToMetres(f : float<ft>) =
f * 0.3048<m> / 1.0<ft>
let totalLength =
100.0<m> + feetToMetres(100.0<ft>)
Notice that our metres-per-foot expression spells out 1.0<ft> rather than 1<ft>. F# only allows units of measure to be applied to floating point values, not integers.
Finally, be aware that units of measure are erased during compilation. At runtime, F# (or rather the CLR) sees only plain old floats. Unit checking is part of the compile phase only.
October 31, 2009 in Software | Permalink | Comments (0) | TrackBack
September 15, 2009
Code Camp Auckland - .NET languages talk
Thanks to everyone who came to the Auckland Code Camp, to all the speakers and especially to the hard-working organisers! Here are the slides from the .NET languages talk:
What's happening in .NET languages - slides (PPTX format)
The demos were basically pretty closely derived from the Expert F# book and can be got from the book's Web site.
September 15, 2009 in Software | Permalink | Comments (0) | TrackBack
TechEd 09 - Visualising data in Silverlight and WPF
Thanks to everyone who came along to the Silverlight and WPF session yesterday. Unfortunately the final demos got a bit rushed but here's the complete code to all the samples which I hope will make a bit more sense when taken with a bit more leisure!
Visualising Data in Silverlight and WPF - slides (PPTX format)
Visualising Data in Silverlight and WPF - demos
September 15, 2009 in Software | Permalink | Comments (0) | TrackBack
September 02, 2009
The case of the missing custom attributes
If you’ve used .NET a lot, you probably haven’t come across the Attribute.TypeId property. This is the key – quite literally – to a problem that doesn’t come up very often – and by “not very often” I mean today I came across it for the second time in eight years – but should never have come up at all and is quite baffling when it does.
Let’s review. .NET allows you to define your own attributes. These attributes can be applied to types, methods, properties, and so on. You can get at these attributes using reflection. Life, in short, is good, at least for people whose desires extend no further than defining custom attributes and retrieving them again.
But .NET also has a sort of shadow type system: an early, hulking kind of dynamic type system tacked onto the side of the .NET 1.0 static type system. It dwells in the System.ComponentModel namespace, TypeDescriptor is its herald, and ICustomTypeDescriptor is its tyrant king (and TypeConverter its capering fool). The purpose of the shadow type system is to allow types to “adjust the truth,” adding properties that they don’t really have but are prepared to fake, and removing properties that they don’t want to talk about. This is jolly useful. It’s what supports, for example, making a Tooltip property appear in the Windows Forms property grid even though no control class actually has a Tooltip property, or applying Dynamic Data attributes to a property in one class by applying them to a field in a completely different class.
For 99.9% of the time – or, to be more exact, for 2920 days out of 2922 – the shadow type system works okay. However, it does have some surprises up its sleeve, and one of those relates to custom attributes. Specifically, if you apply more than one instance of the same custom attribute to a member, the shadow type system will randomly pick one of the instances, and throw the other one away.
Here’s an example. Suppose we define a LocalDisplayNameAttribute class, which can be applied to a property to define a localised display name for a given culture:
[LocalDisplayName(“en-NZ”, “Sweet as”)]
[LocalDisplayName(“en-UK”, “Jolly good, old bean”)]
[LocalDisplayName(“en-US”, “WOO! YOU ROCK!”)]
public bool Yes { get; set; }
And now we ask the shadow type system for these attributes:
var prop = TypeDescriptor.GetProperties(type, “Huzzah”)[0];
var ldns = prop.Attributes.OfType<LocalDisplayNameAttribute>;
Console.WriteLine(ldns.Count());
This prints 1 rather than 3. All instances of LocalDisplayNameAttribute except one have been discarded.
And this is where Attribute.TypeId comes in.
Attribute.TypeId has nothing to do with types, and very little to do with IDs. It is misleadingly named, and misleadingly implemented. Attribute.TypeId’s actual job is to answer the question, “Is this attribute instance a duplicate of this other attribute instance?”
Now the real type system has no problem with duplicate attribute instances. It just stores the attributes and serves them up on demand, without passing judgment. Hey, you wanted duplicates, you can have ’em.
The shadow type system, on the other hand, hates duplicates and makes sure to remove them during its process of “adjusting the truth.” And it uses the TypeId as the criterion for doing so. (Specifically, it uses TypeId as a dictionary key.) And – and this is the kicker – the default implementation for TypeId is to return the attribute type. Consequently, by default, the shadow type system sees all instances of the same attribute type as duplicates to be winnowed down to one. In the example above, the shadow type system decided that the three LocalDisplayNameAttribute instances were duplicates and threw out all but one.
So, finally, we come to the fix.
If you’re creating a custom attribute which allows multiple applications, you almost certainly want to override TypeId to return a unique value for each attribute instance. This could be a smart implementation which returns some appropriate combination of the attribute data, or it could just return a new GUID or even a this reference.
In the LocalDisplayNameAttribute example, as far as we’re concerned, there should be only one instance per culture ID. If someone insists on supplying multiple local display names for the same culture:
[LocalDisplayName(“en-NZ”, “Sweet as”)]
[LocalDisplayName(“en-NZ”, “Choice”)]
then it’s choice and sweet as that the shadow type system recognises these as duplicates and dedupes them for us. But we don’t want these en-NZ display names to come up as duplicates of other culture’s names and cause them to be discarded. So our override of Attribute.TypeId looks like this:
public override object TypeId {
get { return _cultureId; }
}
Parturient montes, nascetur ridiculus mus. Well, better an easy fix than a hard one.
So what do you need to remember?
First, TypeId doesn’t identify a type. It doesn’t really identify anything. It answers the question, “are these two attribute instances duplicates?”
Second, if you’re seeing custom attributes go missing, TypeId is probably the source of the problem.
Third, and consequently, if you’re writing a custom attribute, and it allows multiple instances, you’ll probably want to override TypeId.
You won’t see this very often. Unfortunately, when you do, the documentation is almost completely useless, and the default behaviour is more than a little surprising. So file it away. In 2013, you might just need it.
September 2, 2009 in Software | Permalink | Comments (3) | TrackBack
August 31, 2009
Code Camp Auckland 2009
The now traditional pre-TechEd Auckland Code Camp will be happening on 13 September. In addition to the usual developer festivities there’ll be a SQL Server track, and a security workshop led by the mighty Michael Howard, which should be pretty awesome. And as always it will be free to attend.
August 31, 2009 in Software | Permalink | Comments (0) | TrackBack
August 30, 2009
Those years in marketing taught me nothing
Darryl is running a competition: “If you were talking to an Oracle DBA what would be the top five features of SQL Server that you’d point out to them that makes SQL Server compelling?”
This was my reaction:
If I were talking to an Oracle DBA, the five compelling features I would point out would be ease of use, ease of use, ease of use, ease of use and ease of use.
The Oracle DBA would then roll his eyes, sigh condescendingly and reply, “You see, what you don’t understand is that Oracle isn’t a toy database.”
I would then punch him in the mouth, yell “Not so fucking smug now, are you, you fucker?” and then run away.
This is why I will never win any of Darryl’s competitions.
(In the interests of fairness I should note that this is exactly how Access users perceive software developers, so we have a few planks to take out of our own eyes too.)
August 30, 2009 in Software, Usability | Permalink | Comments (7) | TrackBack
June 10, 2009
Wellington Code Camp – this weekend
It’s been three years since the last (and indeed first) Code Camp in Wellington, so it’s about time we had another one, before the Christchurch guys left us for dust – and now it’s nearly here. So if you haven’t already signed up, and you’re up for a weekend of software architecture, .NET technology and being cut up in the pit lane by the demon Jeremy Boyd, register here and come along.
The schedule’s on the site, and I reckon it’s going to be an interesting mix of technology how-tos and broader architectural and structural talks. We’ve unintentionally ended up with several talks that ask people to take a second look at the way they “naturally” do things, which I think will make for plenty of great discussion and hopefully the occasional “aha!” moment.
Finally, since Mash gets disappointed if I write for too long in plain English, I’d just like to mention asynchronous monads. Thank you and good night.
June 10, 2009 in Software | Permalink | Comments (0) | TrackBack
April 12, 2009
Building Clojure for the CLR
David Miller has announced a port of Clojure, the Lisp dialect for the JVM that’s getting a lot of buzz, to the .NET CLR. Sources are up at the clojure-contrib site.
It’s pretty easy to get it building and running but if you’re using a recent version of the DLR (I was on 21259) then you’ll probably need to make a couple of minor changes:
- ClojureCLR tries to new up ScriptCode in a few places. ScriptCode is now an abstract class, so this causes compiler errors. Changing ScriptCode to LegacyScriptCode seems to fix the problem. (It probably isn’t the right solution, but it’s enough to get things up and running.)
- If you try to use a .NET API call in the REPL, e.g. (Math/Pow 3 4), you get a runtime error of type ArgumentException complaining about a type error in the printToConsole method. To work around this, go into Generator.cs (in the Compiler folder), find the Generate(object, bool) method, locate the if (addPrint) body, and add the line finalExpr = Expression.Convert(finalExpr, typeof(object)); at the top of the body of the if-statement. Again, not sure if this is the right thing to do, but it gets the API calls working.
April 12, 2009 in Software | Permalink | Comments (9) | TrackBack
April 03, 2009
Faster development through less crap
A couple of tips for .NET developers who get frustrated with how slow everything is.
Speeding up XAML editing
To get a much faster and more stable WPF XAML editing experience, right-click a XAML file and choose Open With > Source Code (Text) Editor > Set as Default. This gets you the full XAML editor, with Intellisense, without bogging you down with the visual designer. It is about a million times faster, even compared to the designer’s XAML-only view, especially when you have multiple XAML files open. If you need an excuse to go get some coffee, do your shopping or take a three-month hiking tour of the Himalayas, you still open the visual designer using, wait for it, the View Designer command. (Thanks to Fabrice Marguerie.)
Speeding up MSDN
To get MSDN online to come up quickly in the browser, switch to the low-bandwidth version. You don’t get fancy resizing or buckets of graphics, but you get the content and you get it quick. Click here to see what it’s like and choose “Persist low bandwidth view” if you like it – that way you get the fast view even when following a link to the slow version. (Thanks to Craig Andera.)
April 3, 2009 in Software | Permalink | Comments (2) | TrackBack
April 02, 2009
Mathematics and programming
Jeff Atwood disputes the theory that competent programmers should be mathematically inclined. His conclusion may or may not be correct – I don’t have any evidence one way or the other. His reasoning, however, is wrong.
Jeff observes that “the vast bulk of code that I've seen consists mostly of the ‘balancing your checkbook’ sort of math, nothing remotely like what you'd find in the average college calculus textbook, even,” and gives the example i = j++ / (x + v) -- “not,” he rightly observes, “exactly the stuff mathletes are made of.”
Right, and nothing to do with being mathematically inclined either. Jeff seems to be one of those people who believes that what mathematicians do is sit around doing ever harder calculations. The sort of people who can only imagine Andrew Wiles proved Fermat’s Last Theorem by a fiendishly complicated process of long division.
In reality, the bulk of mathematical effort goes not into performing calculations, but into hypothesising and proving general truths. Let’s take a quick run down of the kind of skills mathematicians really use in doing this:
- Identifying useful abstractions – separating out the salient points of a problem.
- Formulating a path from A to B – building a high-level plan of attack for a problem or proof.
- Turning that plan of attack into a series of precise and rigorous steps, expressed using an abstract and formal notation.
- Bundling up appropriate partial results into handy lemmas – another example of identifying useful abstractions.
- Thinking about special cases that might invalidate the assumptions of the proof or require special handling.
The core skills of mathematics sound awfully like the core skills of programming. It is only “very hard … to draw a direct line from ‘good at math’ to ‘good at programming’” if you confuse mathematics with “mathletics.”
April 2, 2009 in Science, Software | Permalink | Comments (3) | TrackBack