String Hashing in F#

I recently wrote a small program to convert some strings into a ‘unique enough‘ hash which could be used as a short reference.

Whenever I’m trying to come up with an idea of how to handle these kinds of functions, I tend to turn to my favourite language, F#. This allows me to do rapid prototyping in a very functional way.

Below is the prototype version of this hashing program:

open System
open System.Text
open System.Security.Cryptography

let encode (alpha:string, number:int) =

    let b = alpha.Length

    let rec enc (s:string, n:int) =
        match n with
        | x when x <= 0 -> s
        | _ -> enc (s + alpha.[n % b].ToString(), n / b)

    match number with
    | 0 -> alpha.[0].ToString()
    | _ -> enc ("", number)

let md5Int (input:string) =

    let clean (str:string) =
        str.ToLowerInvariant()
           .Trim()

    let computeHash (str:string) =
        let bytes = Encoding.Unicode.GetBytes(str)
        use crypto = new MD5CryptoServiceProvider()
        crypto.ComputeHash(bytes)

    let convert (bytes:byte[]) =
        let i = BitConverter.ToInt32(bytes, 0)
        Math.Abs(i)

    convert (computeHash (clean input))

let hash (input:string) =

    let a = "ABCDFGHJKLMNPQRSTVWXYZ0123456789"
    let i = md5Int input

    encode(a, i)

Once I have this program created, it’s very easy to use in F# Interactive like so:

> hash "Here is a test string!";;
val it : string = "1W2ALLB"
> hash "The hash is much smaller, which is great.";;
val it : string = "5DAF5T"
>