module Hamming
let distance (strand1: string) (strand2: string) : int option =
if strand1.Length <> strand2.Length
then None
else
[ for idx in 0 .. strand1.Length - 1 do
if strand1[idx] <> strand2[idx] then yield 1 else yield 0 ]
|> List.sum
|> Some
Error path
We start by checking if the strings have unequal lengths, and return None
if so:
if strand1.Length <> strand2.Length
then None
Note that we're using string
class' Length
property, not a function like Seq.length
.
Even though F# is a functional-first language, you'll use types (like the string
class) defined in the .NET framework, which is an object-oriented framework.
Inevitably, you'll thus use objects that have methods and properties defined on them.
Don't worry about using methods and objects though, F# is a multi-paradigm language and embraces the interaction with object-oriented code (like the string
class).
Happy path
In the happy path, we know that the strings have the same length so we can use the length (minus one) of the first string as the max of a range of indices to use to access each char
of both string
s and compare them:
for idx in 0 .. strand1.Length - 1 do
The entire for
expression is surrounded by square brackets ([]
) indicating that this is a List comprehension.
This gives you the power of returning intermediate results based on comparing each pair of char
s (returning a 1
when they differ or a 0
if they don't) and then continuing the next pair until you reach the end:
if strand1[idx] <> strand2[idx] then yield 1 else yield 0
The yield
keyword indicates that this concerns an intermediate result, this can also be used in C#.
The resulting list of 1
's and 0
's is then piped into a List.sum to get the hamming distance and finally the result is wrapped in a Some
.
|> List.sum
|> Some