Saturday, September 14, 2013

Should.BeAvailableInF#

Since I first heard of it, I've found the Should Assertions library convenient for the driver programs that stand in for more formal unit tests for code fragments that I want to blog. However, such main programs have to be written in C#, because you can't access C# extension methods on generic open types from F# -- which is exactly what the general run of Should extensions are.

So, you could write F# code like

but that is pretty ugly. And F# type extensions are defined against a specific class, so won't be any use. Which leaves us with generic functions as the best way to wrap the C# extension methods, but

isn't much of an improvement.

The approach that brings us closer to the C# feel would be to make these methods infix operators.

In an ideal world, we'd use ⊦ (U+22A6 ASSERTION) as a lead character, but that's not yet available without forking the compiler, so I chose to write the functions in the form |-{op}, doubling the first character of the {op} for the versions that take custom comparison objects, adding a trailing % for variants taking a message, and using !- as an introducer for unary operations like !-/, where / alludes to ∅ (U+2205 EMPTY SET) for ShouldBeNull.

Apart from the object/generic assertion, the other type that needs transformation across the language barrier is the ShouldThrow<T> extension on Action, which can be wrapped as a generic function taking a unit -> unit, which uses that to create a delegate for the C# world.

Putting it all together we have module fhould, a pun on f for F# and for the old-fashioned cursive long 's' as in ſhould:


Note that there is no order checking in the range tuples (they are just passed as (low, high) to the corresponding arguments of the underlying code); and that 3-ary methods (custom comparers or message strings) have to be invoked in one or other of these styles to get the association correct

and F# syntax doesn't permit us to define unary/generic ShouldBeType or ShouldImplement operators in the style of (!-@)<'a>.


Post a Comment