One of the first things that I like to do in a new language is implement SHA1 . It lets you dig into the language support for the basics.. bit shifts and simple math.

// Converts an ascii string into a byte sequence let getBytes (input: string) = seq {for c in input -> (byte)c} // Get a uint32 from a sequence of 4 bytes in big endian let bytesToUi (input: seq<byte>) = let i = ref 3 // My decrementor function because I didnt realize value assignment don't return a value let dec value = let t = !value value := (!value - 1) t // Fold the 4 bytes into a uint Seq.fold (fun (acc : uint32) (b : byte) -> acc ||| (uint32(b) <<< (dec i) * 8)) 0u input // Rotate left let rotl (input: uint32) (amount) = (input <<< amount) ||| (input >>> (32 - amount)) // Runs SHA1 on a string let sha1 (input: string) = // Get length of input in bytes let messageLen = uint32(input.Length) // Get length of input in bits let bitlen = uint64(8u * messageLen) // Get the amount we need to pad. Include the bit (0x80) we append to the message and the ulong at the end of the message for length let padlen = match ((messageLen + 9u) % 64u) with | 0u -> 0 | _ -> int(64u - ((messageLen + 9u) % 64u)) // Append the bit to the end of the message let asciibytes = Seq.append (getBytes(input)) (Seq.singleton 0x80uy) // Pad with 0s. Assume the length is not going to be larger than uint32, so set the highest order 4 bytes to zero as well let asciibytes = Seq.append asciibytes (seq {for i in 1.. (padlen+4) -> 0uy}) // Append 64 bits of message length let messageBytes = Seq.append asciibytes (seq {for i in (List.rev [0..7]) -> ((byte)(bitlen >>> (i * 8)))}) // Constants let mutable h0 = 0x67452301u let mutable h1 = 0xEFCDAB89u let mutable h2 = 0x98BADCFEu let mutable h3 = 0x10325476u let mutable h4 = 0xC3D2E1F0u // Get the total message length let totalBytes = Seq.length messageBytes // For each 64 byte chunk for chunk = 0 to ((totalBytes / 64)-1) do let w = [| for i in 1 .. 80 -> 0u|] // Populate the array for i = 0 to 15 do w.[i] <- bytesToUi (Seq.take 4 (Seq.skip (i*4 + chunk * 64) messageBytes)) for i = 16 to 79 do w.[i] <- rotl ((w.[i-3]) ^^^ (w.[i-8]) ^^^ (w.[i-14]) ^^^ (w.[i-16])) 1 // Set up the locals let mutable a, b, c, d, e = h0, h1, h2, h3, h4 let mutable k = 0u let mutable f = 0u for i in 0 .. 79 do let round = match i with | m when m < 20 -> (0x5A827999u, ((b &&& c) ||| ((~~~b) &&& d))) | m when m < 40 -> (0x6ED9EBA1u, (b ^^^ c ^^^ d)) | m when m < 60 -> (0x8F1BBCDCu, ((b &&& c) ||| (b &&& d) ||| (c &&& d))) | _ -> (0xCA62C1D6u, (b ^^^ c ^^^ d)) let temp = (rotl a 5) + (snd round) + e + (fst round) + w.[i] e <- d d <- c c <- rotl b 30 b <- a a <- temp h0 <- h0 + a h1 <- h1 + b h2 <- h2 + c h3 <- h3 + d h4 <- h4 + e [h0; h1; h2; h3; h4]

I am no F# expert, but there it is.