Mark Needham

Thoughts on Software Development

F#: Expressing intent and the forward/application operators

with 5 comments

A while ago I wrote about F#'s forward and application operators where I'd looked at how these could be used to simplify code and while trying out Roy Osherove's TDD Kata I realised that perhaps the choice of which of these to use or whether to use them at all depends on what intent we're expressing.

The specific bit of code I was writing was for raising an exception if negative values were provided and I originally thought I'd use the forward operator to express this code:

    let digits = [| 1;2;3;-3 |] 
    let buildExceptionMessage negatives = sprintf "No negative numbers allowed. You provided %s" 
                                                  (String.Join(",", negatives |> Array.map (fun x -> x.ToString())))
 
    raise (ArgumentException (digits |> Array.filter (fun x -> x < 0) |> buildExceptionMessage))

I think in this case the forward operator doesn't actually express the intent of the code better because it puts the focus on the digits rather than on the building of the exception message.

I changed that a bit to emphasise the importance of the 'buildExceptionMessage' function:

raise (ArgumentException (buildExceptionMessage (digits |> Array.filter (fun x -> x < 0))))

I thought it might be possible to get rid of the brackets around the filtering of the digits and instead apply that expression to 'buildExceptionMessage' using the application operator:

raise (ArgumentException (buildExceptionMessage <| digits |> Array.filter (fun x -> x < 0)))

That actually results in the following error message:

Type mismatch. Expecting a  string -> string but given a  'a array -> 'a array. The type 'string' does not match the type ''a array'

The problem is that it applies digits to 'buildExceptionMessage' first and then tries to apply the result of that to Array.filter instead of applying the filter to the digits and then passing the result of that calculation to 'buildExceptionMessage'.

One way to get around this is to remove the forward operator and move digits to be the second argument passed to Array.filter instead:

raise (ArgumentException (buildExceptionMessage <| Array.filter (fun x -> x < 0) digits))

This is the version that I've got at the moment and I think it expresses the intent of the code the best.

I'd be interested in hearing more thoughts on the best way to use or not use these operators in idiomatic F# code.

Written by Mark Needham

January 4th, 2010 at 11:11 am

Posted in F#

Tagged with

5 Responses to 'F#: Expressing intent and the forward/application operators'

Subscribe to comments with RSS or TrackBack to 'F#: Expressing intent and the forward/application operators'.

  1. I'm not quite fluent in F# but I'd say that using both in the same line of code is confusing. And the last expression you suggested is a bit deep.
    Perhaps it is better to split it up in multiple lines.
    Maybe something like:
    let invalidDigits = Array.filter (fun x -> x buildExceptionMessage)
    Naming the Array.filter clarifies what it represents.
    Or maybe my brain is just too small.

    Frank de Groot

    4 Jan 10 at 3:15 pm

  2. Actually that's a good idea I think that'd work quite well, didn't see that.

    So like you say we would end up with this:

    let invalidDigits = Array.filter (fun x -> x < 0) digits

    raise (ArgumentException (buildExceptionMessage invalidDigits))

    Much better I think, thanks!

    Mark Needham

    4 Jan 10 at 3:21 pm

  3. Err, yes that's what I meant. Must have fiddled with the editor too much, the code I posted doesn't make any sense.

    BTW I saw your post on the Feedburner Planet F# list but now it's gone. Is that intended?

    Frank de Groot

    4 Jan 10 at 9:09 pm

  4. Ah maybe wordpress screwed with it or something.

    I'm not sure how Planet F# works actually – I don't do anything to have my posts aggregated on there so I'm not really sure why/why not they'd appear.

    Mark Needham

    4 Jan 10 at 9:28 pm

  5. [...] Mark Needham discusses expressing intent with application operators [...]

Leave a Reply