Which match with indentation rule is at play here? - f#

This indentation works fine:
match 5 with
| k when k < 0 ->
"value is negative"
| k -> "value is non-negative"
|> printfn "%s"
but this does not:
match 5 with
| k when k < 0 ->
"value is negative"
| k ->
"value is non-negative"
|> printfn "%s"
Which F# indentation rule is at play?

This is a combination of indentation under match and special case for operators.
First, under match, the body of each case can start as far left as the vertical line. For example, this works:
match 5 with
| x ->
"some value"
Second, there is a special offset rule for operators that appear at the beginning of a new line: such operators can be to the left of the previous line up to the width of the operator plus one. For example, these all work identically:
let x =
"abc"
|> printf "%s"
let y =
"abc"
|> printf "%s"
let z =
"abc"
|> printf "%s"
So, in your second example, the second case of the match includes the printfn line, because the forward pipe operator is within the acceptable tolerance to the left from the beginning of the first line.
If you move the string "value is non-negative" just two spaces to the right, the forward pipe won't be within the tolerance anymore, and so the printfn line will be interpreted as being outside the match.
match 5 with
| k when k < 0 ->
"value is negative"
| k ->
"value is non-negative"
|> printfn "%s"
In your first example, it is moved 5 spaces to the right, so that works too.

Related

Return the condition in the fitler?

I have the following code to filter a Seq and return the error if nothing returned.
let s = nodes
|> Seq.filter(fun (a, _, _, _) -> if a.ToLower().Contains(key1)) // condition 1
then true
else false // Error message should have Key1
|> Seq.filter(....) // condition 2
|> Seq.filter(....) // condition 3
.....
|> Seq.filter(function // condition N
| _, Some date, _, _ -> date >= StartPeriod
| _ -> false // put StartPeriod in the final message s is not empty before this step
)
if Seq.isEmpty s
then sprintf "Failed by condition 1 (%s) or condition 2 (%s) .... or condition N (Date > %s)"
key1, ...., (StartPeriod.ToShortDateSTring())
else ....
The final error message sprintf will contain all the filter conditions. Is it a way to let the code just return the ones (or just the last one) make the s empty?
Based on rmunn's answer, I modified it to return all the filters that contributed to empty the list.
let rec filterSeq filterList input msgs =
match filterList with
| [] -> input, msgs
| (label, filter) :: filters ->
let result = input |> Seq.filter filter
if result |> Seq.isEmpty then
printfn "The \"%s\" filter emptied out the input" label
Seq.empty, (List.append msgs [label])
else
filterSeq filters result (List.append msgs [label])
let intFiltersWithLabels = [
"Odd numbers", fun x -> x % 2 <> 0
"Not divisible by 3", fun x -> x % 3 <> 0
"Not divisible by 5", fun x -> x % 5 <> 0
"Even numbers", fun x -> x % 2 = 0
"Won't reach here", fun x -> x % 7 <> 0
]
{ 1..20 } |> filterSeq intFiltersWithLabels <| List.empty
What I would do is make a list of filters, and a recursive function that applies them one at a time. If the filter that was just applied returns an empty sequence, then stop, print the filter that just emptied your input, and return that empty sequence. Otherwise keep looping through the recursive function, taking the next filter in the list in turn, until either you end up with no input or you have run through your entire filter list and there's still some input remaining after passing all the filters.
Here's some sample code to illustrate what I mean. Notice how I've put labels in front of each filter function, so that I don't see output like "The <fun:filtersWithLabels#4> filter emptied out the input", but instead I see a sensible human-readable label for each filter.
let rec filterSeq filterList input =
match filterList with
| [] -> input
| (label, filter) :: filters ->
let result = input |> Seq.filter filter
if result |> Seq.isEmpty then
printfn "The \"%s\" filter emptied out the input" label
Seq.empty
else
filterSeq filters result
let intFiltersWithLabels = [
"Odd numbers", fun x -> x % 2 <> 0
"Not divisible by 3", fun x -> x % 3 <> 0
"Not divisible by 5", fun x -> x % 5 <> 0
"Even numbers", fun x -> x % 2 = 0
"Won't reach here", fun x -> x % 7 <> 0
]
{ 1..20 } |> filterSeq filtersWithLabels
// Prints: The "Even numbers" filter emptied out the input
If you want to print all filters until the one that emptied out the input, then you'd just move that printfn call up one line, outside the if expression. The fact that the recursion stops once the input is empty means that you won't see any printfn calls after the filter that emptied out the input.
Note that the way I wrote the function assumes that your original input will not be empty. If your original input was empty, then the function will credit the first filter for emptying the input and will print the first filter's label. You could solve that easily enough by checking for empty input before you check for empty result, but I didn't bother since this is just demo code. Just be aware of this if your real input could ever be empty in your actual use case.
Update: If you need to return a list of labels, not just print them, then make that a second parameter that you pass through your filterSeq function. Something like this:
let matchingFilters filterList input =
let rec filterSeq filterList labelsSoFar input =
match filterList with
| [] -> input, [] // Note NO labels returned in this case!
| (label, filter) :: filters ->
let result = input |> Seq.filter filter
if result |> Seq.isEmpty then
Seq.empty, (label :: labelsSoFar)
else
filterSeq filters (label :: labelsSoFar) result
let result, labels = filterSeq filterList [] input
result, List.rev labels
let filtersWithLabels = [
"Odd numbers", fun x -> x % 2 <> 0
"Not divisible by 3", fun x -> x % 3 <> 0
"Not divisible by 5", fun x -> x % 5 <> 0
"Even numbers", fun x -> x % 2 = 0
"Won't reach here", fun x -> x % 7 <> 0
]
{ 1..20 } |> matchingFilters filtersWithLabels
// Returns: ["Odd numbers"; "Not divisible by 3"; "Not divisible by 5"; "Even numbers"]
A couple things to note about this version of the function: it sounds like what you want is that if the filters run all the way through without emptying out the input, then you want NO filter labels to be returned. If I've misunderstood you, then replace the | [] -> input, [] line with | [] -> input, labelsSoFar to get all the labels in the output. Second thing to note is that I've changed the "shape" of this function: instead of returning a seq, it returns a 2-tuple of (result seq, list of filter labels). The list of filter labels will be empty if the result seq is not empty, but if the result seq ended up empty, then the list of filter labels will contain all the filters that were applied, not just all the filters that reduced the size of the input.
If what you really need is to check whether the size of the input is reduced and print only the labels of filters that filtered something out, then look at Funk's answer for how to check that, but be aware that Seq.length has to run through the entire original sequence and apply all the filters up to that point, each time. So it's a slow operation. If your input data set is large, then it's best to stick with the Seq.empty logic. Play around with it and decide what best fits your needs.
You can separate your logging / error handling code from your business logic by using a decorator.
First, our logger.
open System.Text
type Logger() =
let sb = StringBuilder()
member __.log msg =
sprintf "Element doesn't contain %s ; " msg |> sb.Append |> ignore
member __.getMessage() =
sb.ToString()
Now, we want to wrap Seq.filter so it logs every time we filter out some element(s).
let filterBuilder (logger:Logger) msg f seq =
let res = Seq.filter f seq
if Seq.length seq > Seq.length res then logger.log msg
res
Wrapping up with an example.
let logger = Logger()
let filterLog msg f seq = filterBuilder logger msg f seq
let seq = ["foo" ; "bar"]
let r =
seq
|> filterLog "f"
(fun s -> s.Contains("f"))
|> filterLog "o"
(fun s -> s.Contains("o"))
|> filterLog "b"
(fun s -> s.Contains("b"))
|> filterLog "a"
(fun s -> s.Contains("a"))
logger.getMessage()
val it : string = "Element doesn't contain f ; Element doesn't contain b ; "
"bar" gets filtered out immediately, producing the first message. "foo" goes out the third time around. Also note the second and last pipe in the line don't log any message.

Looking for something like `let` in `match` expression

Sometimes I use something like this:
match foo a with
| 1 -> printfn "%s" (foo a)
| 0 -> printfn "ok"
In this case I call foo function twice and if it is expensive call I use this code:
let tmp = foo a
match tmp with
| 1 -> printfn "%s" tmp
| 0 -> printfn "ok"
But in this case I have created variable with outer scope (regarding match expression).
I am looking for something like this:
match (foo a) as tmp with
| 1 -> printfn "%s" tmp
| 0 -> printfn "ok
What do you use in this cases ? Is there any elegant solution ?
Update - real example:
let collection = getValuesFromDatabase a
match Array.length collection with
| 0 -> printfn "nothing"
| _ -> bar collection.[0]
Option 1: use a let- or do-block
let result =
let tmp = foo a
match tmp with
| 1 -> printfn "%d" tmp
| 0 -> printfn "ok"
Nesting the whole thing under a let-block keeps from polluting the namespace with tmp. The syntax is a bit heavy, but in return it allows for arbitrary complexity of the local computation.
Alternatively, if your result is a unit, you can replace let with do:
do
let tmp = foo a
match tmp with
| 1 -> printfn "%d" tmp
| 0 -> printfn "ok"
Option 2: use pattern aliasing
When pattern-matching, you can match a value with more than one pattern at once, separating the patterns with &, e.g.:
match [1;2;3] with
| (x::_)&(_::y::_) -> printfn "First element is %d, second element is %d" x y
Here, I am matching the same list with two patterns: x::_ and _::y::_. The example is a bit silly (I could have just matched with x::y::_), but it conveys the idea.
In your example, you can use this mechanism to capture the whole value by matching it with a trivial pattern:
match foo a with
| 1&x -> printfn "%d" x
| 0 -> printfn "ok"
Update: the "real" example
This is in response to your edit, where you provided a "real" example, which deals with a collection.
This "real" example is actually different from the "toy" examples that you provided before, in that you want to capture collection, but you're matching on Array.length collection - not the same thing. In general, there is no shortcut for this, except putting it in a nested do or let block as described above. But in your specific case I could rewrite the match like this:
match getValuesFromDatabase a with
| [||] -> printfn "nothing"
| xs -> bar xs.[0]
Here, instead of calling Array.length, I match the value with an empty array. This way, since I'm matching the collection itself, I can capture it in the second match case and use it to get the first element.
If you wanted to perform a more complex check than just the empty array check, you could also use a pattern guard:
match getValuesFromDatabase a with
| xs when Array.length xs = 0 -> printfn "nothing"
| xs -> bar xs.[0]
In your real example, you can just use if. You are not really pattern matching on any complex data type which is where match shines. If you're testing whether a collection is empty, you can just write something like:
let collection = getValuesFromDatabase a
if Array.length collection = 0 then printfn "nothing"
else bar collection.[0]

Incomplete pattern match when two patterns share a `when` clause

A common surprise for beginning F# programmers is the fact that the following is an incomplete match:
let x, y = 5, 10
match something with
| _ when x < y -> "Less than"
| _ when x = y -> "Equal"
| _ when x > y -> "Greater than"
But I just encountered a situation that surprised me. Here's a small bit of sample code to demonstrate it:
type Tree =
| Leaf of int
| Branch of Tree list
let sapling = Branch [Leaf 1] // Small tree with one leaf
let twoLeafTree = Branch [Leaf 1; Leaf 2]
let describe saplingsGetSpecialTreatment tree =
match tree with
| Leaf n
| Branch [Leaf n] when saplingsGetSpecialTreatment ->
sprintf "Either a leaf or a sapling containing %d" n
| Branch subTree ->
sprintf "Normal tree with sub-tree %A" subTree
describe true sapling // Result: "Either a leaf or a sapling containing 1"
describe false sapling // Result: "Normal tree with sub-tree [Leaf 1]"
describe true twoLeafTree // Result: "Normal tree with sub-tree [Leaf 1; Leaf 2]"
describe false twoLeafTree // Result: "Normal tree with sub-tree [Leaf 1; Leaf 2]"
This version of the describe function produced the "Incomplete pattern matches on this expression" warning, even though the pattern match is, in fact, complete. There are no possible trees that will not be matched by that pattern match, as can be seen by removing the specific branch of the match that had a when expression in it:
let describe tree =
match tree with
| Leaf n -> sprintf "Leaf containing %d" n
| Branch subTree ->
sprintf "Normal tree with sub-tree %A" subTree
This version of describe returns the "Normal tree" string for both the sapling and twoLeafTree trees.
In the case where the match expression contains nothing but when expressions (like the first example where x and y are being compared), it is reasonable that the F# compiler might not be able to tell whether the match will be complete. After all, x and y might be types with a "weird" implementation of comparison and equality where none of those three branches are true.*
But in cases like my describe function, why doesn't the F# compiler look at the pattern, say "If all the when expressions evaluated to false, there would still be a complete match" and skip the "incomplete pattern matches" warning? Is there some specific reason for this warning showing up here, or is it just a case of the F# compiler being just a little bit simplistic here and giving a false-positive warning because its code wasn't sophisticated enough?
* In fact, it is possible to set x and y to values such that x < y, x = y, and x > y are all false, without ever stepping outside the "normal" bounds of the standard .Net type system. As a special bonus question/puzzle, what are these values of x and y? No custom types needed to answer this puzzle; all you need is types provided in standard .Net.
In F# match syntax, the when guards apply to all cases enumerated just before it, not just to the last one.
In your specific scenario, the guard when saplingsGetSpecialTreatment applies to both Leaf n and Branch [Leaf n] cases. So this match will fail for the case when tree = Leaf 42 && saplingsGetSpecialTreatment = false
The following would be complete, since the Leaf case now has its own branch:
let describe saplingsGetSpecialTreatment tree =
match tree with
| Leaf n ->
sprintf "Either a leaf or a sapling containing %d" n
| Branch [Leaf n] when saplingsGetSpecialTreatment ->
sprintf "Either a leaf or a sapling containing %d" n
| Branch subTree ->
sprintf "Normal tree with sub-tree %A" subTree
Just clarifying Fyodor's post with an extra example. Think of it as a when y = 3 section, an otherwise section, and then, for everything else
let f y x =
match x with
| 0
| 1
| 2 when y = 3 -> "a"
| 0
| 1
| 2 -> "b"
| _ -> "c"
[0 .. 3] |> List.map (f 3)
[0 .. 3] |> List.map (f 2)
FSI
val f : y:int -> x:int -> string
> val it : string list = ["a"; "a"; "a"; "c"]
> val it : string list = ["b"; "b"; "b"; "c"]
So, is this a sensible default? I think so.
Here's a more explicit version:
let f2 y x =
match x,y with
| 0,3
| 0,3
| 0,3 -> "a"
| 0,_
| 1,_
| 2,_ -> "b"
| _ -> "c"
[0 .. 3] |> List.map (f2 3)
[0 .. 3] |> List.map (f2 2)
... and a more compact version:
let f3 y x = x |> function | 0 | 1 | 2 when y = 3 -> "a"
| 0 | 1 | 2 -> "b"
| _ -> "c"

Match a number if it is multiple of 2

I'm learning f# and currently I'm with the match keyword. I'm modifying the next example, to print into the screen if a numbers is multiple of 2, it's mod is 0.
[<Literal>]
let Three = 3
let filter123 x =
match x with
// The following line contains literal patterns combined with an OR pattern.
| 1 | 2 | Three -> printfn "Found 1, 2, or 3!"
// The following line contains a variable pattern.
| var1 -> printfn "%d" var1
for x in 1..10 do filter123 x
I have modified it and coded an additional match for:
| x % 2 == 0 -> printfn "it's multiple of 2!"
But that doesn't work, it says that "%" it's an undefined symbol... any ideas? Thanks!
This is a classic Tim Toady. The other answers are perfectly correct. I would add a couple of variations:
// Eugene's answer
let filterEven1 x =
match x with
| _ when x % 2 = 0 -> printfn "%d is even!" x
| _ -> printfn "%d is not even" x
// equivalent to above, but with "function" match syntax
let filterEven2 = function
| x when x % 2 = 0 -> printfn "%d is even!" x
| x -> printfn "%d is not even" x
// variation on Gene's answer
let (|Even|Odd|) x =
if x % 2 = 0 then Even(x) else Odd(x)
let filterEven3 = function
| Even(x) -> printfn "%d is even!" x
| Odd(x) -> printfn "%d is not even" x
// probably how I would do it
let filterEven4 x =
match x % 2 with
| 0 -> printfn "%d is even!" x
| _ -> printfn "%d is not even" x
You cannot use an expression as a match case. Another alternative to a guarded pattern would be defining an active pattern:
let(|Even|Odd|) (x:int) =
if x % 2 = 0 then Even else Odd
and then using it as a normal pattern case
.......
| Even -> printfn "it's multiple of 2!"
.......
You need to use guarded pattern rule:
| _ when x % 2 = 0 -> printfn "it's multiple of 2!"

How to code Fizzbuzz in F#

I am currently learning F# and have tried (an extremely) simple example of FizzBuzz.
This is my initial attempt:
for x in 1..100 do
if x % 3 = 0 && x % 5 = 0 then printfn "FizzBuzz"
elif x % 3 = 0 then printfn "Fizz"
elif x % 5 = 0 then printfn "Buzz"
else printfn "%d" x
What solutions could be more elegant/simple/better (explaining why) using F# to solve this problem?
Note: The FizzBuzz problem is going through the numbers 1 to 100 and every multiple of 3 prints Fizz, every multiple of 5 prints Buzz, every multiple of both 3 AND 5 prints FizzBuzz. Otherwise, simple the number is displayed.
Thanks :)
I think you already have the "best" solution.
If you want to show off more functional/F#-isms, you could do e.g.
[1..100]
|> Seq.map (function
| x when x%5=0 && x%3=0 -> "FizzBuzz"
| x when x%3=0 -> "Fizz"
| x when x%5=0 -> "Buzz"
| x -> string x)
|> Seq.iter (printfn "%s")
and use lists, sequences, map, iter, patterns, and partial application.
[1..100] // I am the list of numbers 1-100.
// F# has immutable singly-linked lists.
// List literals use square brackets.
|> // I am the pipeline operator.
// "x |> f" is just another way to write "f x".
// It is a common idiom to "pipe" data through
// a bunch of transformative functions.
Seq.map // "Seq" means "sequence", in F# such sequences
// are just another name for IEnumerable<T>.
// "map" is a function in the "Seq" module that
// applies a function to every element of a
// sequence, returning a new sequence of results.
(function // The function keyword is one way to
// write a lambda, it means the same
// thing as "fun z -> match z with".
// "fun" starts a lambda.
// "match expr with" starts a pattern
// match, that then has |cases.
| x when x%5=0 && x%3=0
// I'm a pattern. The pattern is "x", which is
// just an identifier pattern that matches any
// value and binds the name (x) to that value.
// The "when" clause is a guard - the pattern
// will only match if the guard predicate is true.
-> "FizzBuzz"
// After each pattern is "-> expr" which is
// the thing evaluated if the pattern matches.
// If this pattern matches, we return that
// string literal "FizzBuzz".
| x when x%3=0 -> "Fizz"
// Patterns are evaluated in order, just like
// if...elif...elif...else, which is why we did
// the 'divisble-by-both' check first.
| x when x%5=0 -> "Buzz"
| x -> string x)
// "string" is a function that converts its argument
// to a string. F# is statically-typed, so all the
// patterns have to evaluate to the same type, so the
// return value of the map call can be e.g. an
// IEnumerable<string> (aka seq<string>).
|> // Another pipeline; pipe the prior sequence into...
Seq.iter // iter applies a function to every element of a
// sequence, but the function should return "unit"
// (like "void"), and iter itself returns unit.
// Whereas sequences are lazy, "iter" will "force"
// the sequence since it needs to apply the function
// to each element only for its effects.
(printfn "%s")
// F# has type-safe printing; printfn "%s" expr
// requires expr to have type string. Usual kind of
// %d for integers, etc. Here we have partially
// applied printfn, it's a function still expecting
// the string, so this is a one-argument function
// that is appropriate to hand to iter. Hurrah!
My example is just a minor improvement over the code posted by 'ssp'. It uses parameterized active patterns (which take the divisor as an argument). Here is a more in-depth explanation:
The following defines an active pattern that we can later use in the match
expression to test if a value i is divisible by a value divisor. When we write:
match 9 with
| DivisibleBy 3 -> ...
...it means that the value '9' will be passed to the following function as i and the value 3 will be passed as divisor. The name (|DivisibleBy|_|) is a special syntax, whith means that we're declaring an active pattern (and the name can appear in the
match on the left side of ->. The |_| bit means that the pattern can fail (our example fails when value is not divisible by divisor)
let (|DivisibleBy|_|) divisor i =
// If the value is divisible, then we return 'Some()' which
// represents that the active pattern succeeds - the '()' notation
// means that we don't return any value from the pattern (if we
// returned for example 'Some(i/divisor)' the use would be:
// match 6 with
// | DivisibleBy 3 res -> .. (res would be asigned value 2)
// None means that pattern failed and that the next clause should
// be tried (by the match expression)
if i % divisor = 0 then Some () else None
Now we can iterate over all the numbers and match them against patterns (our active pattern) using match (or using Seq.iter or some other technique as shown in other answers):
for i in 1..100 do
match i with
// & allows us to run more than one pattern on the argument 'i'
// so this calls 'DivisibleBy 3 i' and 'DivisibleBy 5 i' and it
// succeeds (and runs the body) only if both of them return 'Some()'
| DivisibleBy 3 & DivisibleBy 5 -> printfn "FizzBuzz"
| DivisibleBy 3 -> printfn "Fizz"
| DivisibleBy 5 -> printfn "Buzz"
| _ -> printfn "%d" i
For more information on F# active patterns, here is an MSDN documentation link. I think that if you remove all the comments, the code will be slightly more readable than the original version. It shows some quite useful tricks :-), but in your case, the task is relatively easy...
Yet one solution in F# style (i.e. with Active Patterns usage):
let (|P3|_|) i = if i % 3 = 0 then Some i else None
let (|P5|_|) i = if i % 5 = 0 then Some i else None
let f = function
| P3 _ & P5 _ -> printfn "FizzBuzz"
| P3 _ -> printfn "Fizz"
| P5 _ -> printfn "Buzz"
| x -> printfn "%d" x
Seq.iter f {1..100}
//or
for i in 1..100 do f i
To add one more possible answer - here is another approach without pattern matching. It uses the fact that Fizz + Buzz = FizzBuzz, so you don't actually need to test for all three cases, you only need to see if it is divisible by 3 (then print "Fizz") and also see if it is divisible by 5 (then print "Buzz") and finally, print a new line:
for i in 1..100 do
for divisor, str in [ (3, "Fizz"); (5, "Buzz") ] do
if i % divisor = 0 then printf "%s" str
printfn ""
The nested for loop assignes 3 and "Fizz" to divisor and str in the first iteration and then the second pair of values in the second iteration. The beneift is, you could easily add printing of "Jezz" when the value is divisible by 7 :-) ...in case that extensibility of the solution is a concern!
Here's one more:
let fizzy num =
match num%3, num%5 with
| 0,0 -> "fizzbuzz"
| 0,_ -> "fizz"
| _,0 -> "buzz"
| _,_ -> num.ToString()
[1..100]
|> List.map fizzy
|> List.iter (fun (s:string) -> printfn "%s" s)
I find this to be a bit more readable answer edited was inspired a bit by the others
let FizzBuzz n =
match n%3,n%5 with
| 0,0 -> "FizzBuzz"
| 0,_ -> "Fizz"
| _,0 -> "Buzz"
| _,_ -> string n
[1..100]
|> Seq.map (fun n -> FizzBuzz n)
|> Seq.iter (printfn "%s")
Here is my version:
//initialize array a with values from 1 to 100
let a = Array.init 100 (fun x -> x + 1)
//iterate over array and match *indexes* x
Array.iter (fun x ->
match x with
| _ when x % 15 = 0 -> printfn "FizzBuzz"
| _ when x % 5 = 0 -> printfn "Buzz"
| _ when x % 3 = 0 -> printfn "Fizz"
| _ -> printfn "%d" x
) a
This is my first program in F#.
It's not perfect, but I think someone who starts learning F# (like me :)) can figure out what happens here quite fast.
However I am wondering what is the difference between matching to any _ or to x itself in pattern matching above?
I couldn't find a working solution that didn't include testing for i % 15 = 0. I've always felt that not testing for that is part of this "stupid" assignment. Be aware that this is probably not idiomatic F# since it's my first program in the language.
for n in 1..100 do
let s = seq {
if n % 3 = 0 then yield "Fizz"
if n % 5 = 0 then yield "Buzz" }
if Seq.isEmpty s then printf "%d"n
printfn "%s"(s |> String.concat "")
Here's a version emphasizing a generic tuple list of carbonations:
let carbonations = [(3, "Spizz") ; (5, "Fuzz"); (15, "SpizzFuzz");
(30, "DIZZZZZZZZ"); (18, "WHIIIIII")]
let revCarbonated = carbonations |> List.sort |> List.rev
let carbonRoute someCarbonations findMe =
match(List.tryFind (fun (x,_) -> findMe % x = 0) someCarbonations) with
| Some x -> printfn "%d - %s" findMe (snd x)
| None -> printfn "%d" findMe
let composeCarbonRoute = carbonRoute revCarbonated
[1..100] |> List.iter composeCarbonRoute
I don't like all these repeated strings, here's mine:
open System
let ar = [| "Fizz"; "Buzz"; |]
[1..100] |> List.map (fun i ->
match i % 3 = 0, i % 5 = 0 with
| true, false -> ar.[0]
| false, true -> ar.[1]
| true, true -> ar |> String.Concat
| _ -> string i
|> printf "%s\n"
)
|> ignore
Here is an attempt that factors out the modulo checks
let DivisibleBy x y = y % x = 0
[ 1 .. 100 ]
|> List.map (function
| x when DivisibleBy (3 * 5) x -> "fizzbuzz"
| x when DivisibleBy 3 x -> "fizz"
| x when DivisibleBy 5 x -> "buzz"
| x -> string x)
|> List.iter (fun x -> printfn "%s" x)
Here is how I refined it

Resources