F# - Things I Learned Today

I was playing around a bit today with F#, trying to write some real code that interfaces with WPF. Here are a few things I found – very much a “note to self” thing, but if you happen to be interested, please comment or ask.

Number 1 - implementing interfaces that include events is a PITA

I was trying to implement INotifyPropertyChanged, which contains the event PropertyChanged. Eventually I found a working description in this forum thread. I’ve now implemented the interface and a helper method to fire the event like this:

interface INotifyPropertyChanged with
  member x.add_PropertyChanged(handler: PropertyChangedEventHandler) =
    x.notifyPropertyChangedHandlers <- (Delegate.Combine(x.notifyPropertyChangedHandlers, handler) :?> PropertyChangedEventHandler)
  member x.remove_PropertyChanged(handler: PropertyChangedEventHandler) =
    x.notifyPropertyChangedHandlers <- (Delegate.Remove(x.notifyPropertyChangedHandlers, handler) :?> PropertyChangedEventHandler)

member private x.PropertyChanged(propertyName) =
  x.notifyPropertyChangedHandlers.Invoke(x, new PropertyChangedEventArgs(propertyName))

No idea whether this is the best way - at this point I found for the first time that documentation is currently badly lacking… no mention of anything like this in any official place I could find, nor in Don Syme’s or Robert Pickering’s books (the latter wrote the forum reply at least <g>). Was this forgotten? What’s worse than having no docs is that there are so many outdated examples around that I spent half the time trying something that obviously didn’t work any longer because the approach had been revised.

Number 2 - class syntax has a lot of weird restrictions

Yeah, well… weird is perhaps not the right word, I admit. But it certainly seems weird, since they’ve just invented two entirely different sets of valid elements for classes with implicit construction sequences and those without. Basically I had a class that was instantiated with a Window reference and hooked up to an event from that Window. Handling that event, the class was performing a calculation and then it was supposed to fire a property changed event. Now, to fire the event correctly, of course I need a reference to the current instance, which for some reason is only available in members (those that use the member keyword), not in function values created using the let keyword. The reason for that is probably that the let elements are only valid in an implicit initialization sequence and as such they’re practically part of the constructor code.

Still, it took a while for me to realize that, since in most languages there’s a reference to the current instance available in the constructor – it’s probably a good idea not to have that reference in the constructor, since it prevents calling members before initialization is complete. Anyway, so my event handler for the Window event had to be a member itself, not just a function value as I’d had it before. The problem was that in this case I needed a reference to the current instance to even hook up the event, which wasn’t available to me because I was using a construction sequence. There is a syntax for explicit constructors that allows creating a reference to the current instance. This is still implemented cleanly, because the syntax requires that first a constructor (not necessarily the same one) has to run and initialize all values, before the additional block is executed that can access the current instance.

Using that syntax in conjunction with my initialization sequence wasn’t really working, so I had to convert my class entirely to using just an explicit constructor. That involves getting rid of all lets, using vals for all fields, can’t use in-place initialization and so on… So, just in case anybody reads this who’s in a discussion mood – I’m aware that in the end it’s all my fault 😃 But it is pretty hard to figure out how this all works, I didn’t find it to be well documented anywhere, and the compiler messages are really crappy about half the time.

Number 3 - Buggy behaviour of the"new() = { ... } then ... syntax

This is the syntax I referred to before. In general it works fine – only I found that the compiler is really anal about the formatting of the expression, at least in #light syntax mode. I tried it without the #light at some point and found that it was actually more tolerant - but I had other trouble with that (doesn’t warrant an entry here since I didn’t investigate in depth - basically my “class” and “end” keywords allegedly didn’t match up whatever I did) and so I switched back to #light. In the end I got it working by formatting like this - all sorts of variations easily break things.

new(state: int) as x =
  { state = state;
    blah = "hi" }
    x.state <- x.state * x.state

Number 4 - class type eating up “do” block behind it, in spite of indentation

I had my main code file formatted along these lines:

type MyClass =
  ... stuff in my class

  ... stuff to get my app running

That’s what I had the whole time, and I guess an important detail might be that I had a do block in my class while I was using the implicit initialization sequence. Later I removed the do block, and when I finally got everything to compile without errors (that stupid formatting thing with the new() above took me quite a while), suddenly my application wasn’t doing anything at all anymore! I placed a breakpoint on the first line of the app start block and execution didn’t even get there. I found the source of that problem by looking at the compiled app with Reflector. Surprisingly, my startup method was entirely empty, and the code in that do block, even though clearly indented to live outside the class, had been pulled into a static constructor for the class. Wow. I haven’t had the need yet to actually create a static class constructor in F#, but my guess is that it uses a similar syntax. Anyway, given the indentation it seems pretty clear to me that in this case this shouldn’t happen. Well, who knows… Anyway, I fixed the problem by adding class and end to the class type, so my code looks like this now:

type MyClass = class
  ... stuff in my class

  ... stuff to get my app running

Oh yeah – and why did I have that class in the same file in the first place? Well… I’ve previously blogged about some weird things with namespaces in F#, and apparently that wasn’t the end of it. I tried to move the class into a different file and put it into an explicit namespace, but whatever I did, the compiler insisted that it couldn’t see the class in that block of code that becomes the startup method of a Windows application. Yes, I had an open line in that file of course. Another thing to investigate further, since I have no plausible idea what was going on there.

Sorry, this blog does not support comments.

I used various blog hosting services since this blog was established in 2005, but unfortunately they turned out to be unreliable in the long term and comment threads were lost in unavoidable transitions. At this time I don't want to enable third-party services for comments since it has become obvious in recent years that these providers invariably monetize information about their visitors and users.

Please use the links in the page footer to get in touch with me. I'm available for conversations on Keybase, Matrix, Mastodon or Twitter, as well as via email.