Heap Heap Array! Rotating Header Image

Rough Edges

My copy of Programming F# arrived a few days ago, and I’ve been reading it in my spare time. In doing so, I’ve noticed a few oddities in the language. That isn’t to say that it isn’t a great language; it’s just clear that the integration between ML and the .NET framework is not entirely seamless.

Explicit Interface Implementation

Why are all interfaces implemented explicitly, making it necessary to cast an object reference to an interface type before using any of the members of that interface? I thought requiring that sort of redundant bullcrap was phased out with COM. The compiler knows what interfaces the class implements; shouldn’t it be able to determine, at least in the simple case, whether you’re calling something on an interface?

I mean, the compiler should be able to figure this out:

// Borrowed with modification from "Programming F#"
type IDoStuff =
    abstract DoStuff : unit -> unit

type Foo() =
    interface IDoStuff with
        override this.DoStuff() = printfn "Doing stuff..."

let x = new Foo()

// This fails with a compiler error
x.DoStuff()

// This works.
(x :> IDoStuff).DoStuff()

// This works too.
let y = x :> IDoStuff
y.DoStuff()

Don’t get me wrong; I understand the utility of explicit interface implementation, at least when member names collide. But is it really necessary to require all interface members be explicit?

Note that this only applies to classes implemented in F#. Classes implemented in C# have the option of implementing interfaces implicitly, and F# can use those interfaces without casting. In VB.NET, interfaces are implemented explicitly, but generally with a method with the same name:

Public Interface IDoStuff
    Sub DoStuff()
    Sub DoMoreStuff()
End Interface

Public Class Class1
    Implements IDoStuff

    Public Sub DoStuff() Implements IDoStuff.DoStuff
        Console.WriteLine("Doing Stuff")
    End Sub

    Public Sub AnotherMethod() Implements IDoStuff.DoMoreStuff
        Console.WriteLine("Doing More Stuff")
    End Sub
End Class

Calling it from F# works much the same way:

let x = new ClassLibrary1.Class1()

// This works, since the method has the same name in the interface and class.
x.DoStuff()

// You can't call the interface method...
x.DoMoreStuff() // (fails with a compile error)

// ... but you can call the implementing method directly.
x.AnotherMethod()

// Or you can use the upcast operator.
(x :> ClassLibrary1.IDoStuff).DoMoreStuff()

Mutually Exclusive Exception-Handling Keywords

Why can’t catch and finally be combined? The only other language I’m aware of that doesn’t allow combining of these forms is Python, and that’s only versions prior to 2.5. Hell, even VB.NET can combine catch and finally.

Extension Methods

When you add an extension method in F#, it only works with other F# code. You can’t call an extension method defined in F# from C# or VB.NET code. Granted, given the hassles involved in setting up extension methods in C# or VB.NET, this isn’t surprising, and probably for the best; within F#, extension methods are easy, and forcing compatibility with other languages would make them unwieldy. But still, having the option would be nice.

Overall, I’m pleased with F#. As a standalone language, it’s fairly impressive. While the .NET integration is a bit rough around the edges, it’s tied in well enough to act as an effective Trojan horse, bringing functional programming to .NET-only shops. And that’s worth the hassle.

Leave a Reply