Having spent some time programming in F#, I though I’d post some observations that might be useful to C# programmers.

  • F# has an ambiguity with regard to the return statement. It’s not required in a function, but when you are in a match block, you do need it:

    match root.Name.ToString() with
    | "rss" -> return ProcessAsRss(root, url)
    | "atom" -> return ProcessAsAtom(root, url)
    | _ -> return 0
    

  • F# has something against null. Apparently, you cannot really have null objects without hacks. Which was a problem for me because I was trying to write

    let id = null
    
    to use it as an output parameter in a sproc. I got so confused I had to ask on SO, and ended up writing somewhat bizarre code:
    let id = new Nullable<int>()
    Somewhat predictably, the int? syntax is not working – F# tells me that the use of a ? symbol after an identifier is reserved for future use.

  • You cannot call a function that returns something and then continue doing things. Without the return statement, F# thinks that a returning function is the return value. Which leads to code like the following

    let _ = ctx.ChannelUpsert(ref id, url,
                              ⋮
                             )
    
    The underscore stores the end result, even though we don’t really care.

  • One of the really useful methods for downloading from the web was removed from F# in order to allow for compatibility with Silverlight and Mono. This function defines a matching pair of Begin and End clauses for a web request, thus allowing asynchronous operation:

    type WebRequest with
      member x.GetResponseAsync() =
        Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse)

  • The async keyword is really fun syntactic sugar that also exists in C# (in a way) via PowerThreading’s AsyncEnumerator, though this usage is somewhat more clever. Essentially, in addition to an immediate variable-definition operator let, F# also has a ‘whenever’ operator let! (with an exclamation mark). This operator appears precisely at an async junction, i.e., on the left-hand side of an async call:

    let UpsertFromUrl(url:string) =
      async {
        try
          let r = WebRequest.Create(url)
          let! resp = r.GetResponseAsync()
          use stream = resp.GetResponseStream()
          use reader = new StreamReader(stream)
          let xml = reader.ReadToEnd()
          ⋮
      }
    

  • It seems the whole point of async ops is to fire them off on arrays (sorry, sequences). It is this way in PowerThreading, and it appears this way in F#.

    let UpdateExistingChannels =
      use ctx = new PrioryDataContext()
      ctx.Channels
      |> Seq.map (fun f -> UpsertFromUrl(f.Source))
      |> Async.Parallel
      |> Async.Run
    
    The funny thing is: I wonder how many people will use this instead of, say, doing Parallel.Invoke() instead. ← This is C# 4 library stuff, btw. We’re not even there yet.

  • F# has a use keyword to match C#’s using, but it’s not clear where its scope is. F# does not really delimit its scope with curly braces (exce, and indenting doesn’t help either. Figures.

  • Strings lose their == operator, so you can no longer compare them this way. Actually, I was also comparing string and XName and the like, and I suspect that I might have panicked. Also – and this is annoying – the compiler did not list the error! It just failed to compile and I had to check the build output to see what was going on. How crazy is that?!?

  • I managed my first F# hack!!! (err, of sorts) I was trying to do an upsert on all elements of an array, and then return the array, but whatever I did, F# was complaining that my List.iter code was not to its liking. So, instead, I used List.map taking the return value of my upsert sprocs and returning the length of that list. All in one statement. Witness my perfection:

      first.Elements() 
      |> Seq.filter(fun f -> f.Name.Equals("item"))
      |> Seq.map(fun f -> ctx.ItemUpsert(ref itemId, id, 
                                         ⋮
                                        )
      |> Seq.length
    
    Programming is great!