F# wrapper to generate SHA256 signature for a file I've created the following module to allow me to generate a SHA256 signature for a file. (In real life this is used to verify an image file hasn't been amended).  The cut down code looks like this:

open System.IO
open System.Text
open System.Security.Cryptography;


// Get the SHA256 hash of a file
let SHA256 (file:FileInfo) =
    let FileSHA256Wrap (hashFile : FileStream) (sha256Hash : SHA256)  : byte[] = 
        sha256Hash.ComputeHash(hashFile)
    let FileWrap (hashFile : FileStream) : byte[] =
        using (SHA256Managed.Create()) (FileSHA256Wrap hashFile)
    using (file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) FileWrap

// Convert the byte[] version of the hash to a printable encoded HEX string
let HexEncoded (hash:byte[]) :string =
    let sb = new StringBuilder(hash.Length * 2)
    hash |&gt; Array.map (fun c -&gt; sb.AppendFormat("{0:X2}",c)) |&gt; ignore
    sb.ToString()

// Get the file hash and convert it to a HEX string
let HexEncodedSHA256 (file:FileInfo) =
    file |&gt; SHA256 |&gt; HexEncoded


let fi = new FileInfo("somefile.tif")
HexEncodedSHA256 fi


I've two questions here, with the double using statements I find the wrap functions help me work out what is going on - but is there a neater and more succinct way to write this without making it hard to work out what is happening?

The implementation of HexEncoded uses a string builder, is there a more functional way to do this.
The use binding is usually better than the using function. The object is disposed when leaving the scope of the use binding (when leaving the SHA256 function).

let SHA256 (file:FileInfo) =
    use hashFile = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
    use sha256Hash = SHA256Managed.Create()
    sha256Hash.ComputeHash(hashFile)


You can avoid the use of a string builder by using String.concat. You can also use the F# sprintf function, which has slightly different format specifier syntax.

let HexEncoded (hash:byte[]) :string =
    hash
    |&gt; Array.map (sprintf "%02X")
    |&gt; String.concat ""


This might be slightly slower than your string builder because it requires an intermediate array. (Note that your implementation could remove the intermediate array by using Array.iter instead of Array.map and moving the ignore to inside the lambda.)