Thursday, June 10, 2010

F# Tricks: Collecting Some Optional Values

Skip this post if you have no idea what F# is, and think LINQ is stupid.

When you map inputs to outputs with a function that can return None, or Some Output, you get an annoying issue of having a list containing Nones, and Somes. For example:

// Contains both encrypted and un-encrypted files: 
let listOfFiles:Seq

// Return a decrypted File, or None if the file can't be decrypted.
let decryptFile file
match file with
| isFileDecryptable file -> Some DecryptFile file
| _ -> None

// decryptedFiles contains Nones, intertwined with some Some DecryptedFiles
let decryptedFiles = listOfFiles |> Seq.map decryptFile
Here are two ways to remedy that:

// To get a list of only decrypted files you could do:
let realDecryptedFiles = decryptedFiles |> Seq.filter Option.isSome |> Seq.map Option.get

// However, I prefer the more concise version of:
let realDecryptedFiles = decryptedFiles |> Seq.collect Option.toList
If you're an F# guru I'd love to hear your thoughts on this.