Mark Needham

Thoughts on Software Development

Archive for the ‘F#’ Category

F#: Refactoring to pattern matching

with 12 comments

I was looking through some of the F# code I’ve written recently and I realised that I was very much writing C# in F# with respect to the number of if statements I’ve been using.

I thought it would be interesting to see what the code would look like if I was able to refactor some of that code to make use of pattern matching instead which would be a more idiomatic way of solving the problem in F#.

The first example of if statements is in my post about my F# solution to Roy Osherove’s TDD Kata.

I originally wrote a parse function which was able to parse a string and give it’s decimal value or 0 if it couldn’t be parsed.

let parse value = 
    let (itParsed, value) = Decimal.TryParse value
    if (itParsed) then value else 0.0m

If we use a pattern match expression we’d end up with the following:

let parse value = match Decimal.TryParse value with | (true, value) -> value | (false, _) -> 0.0m

The neat thing about this approach is that we don’t need to store the result of the ‘Decimal.TryParse’ function as we did in my original version.

We could in theory also write it like this…

let parse value = match Decimal.TryParse value with | (true, value) -> value | (_, _) -> 0.0m

…but while that is slightly less code I quite like the other version because it’s a bit more intention revealing that 0 will be returned if we fail to parse the string. I think there’s less thinking needed to understand the code.

Another example is this bit of code:

let add value = if ("".Equals(value) or "\n".Equals(value)) then 0.0m
                else match digits value |> Array.filter (fun x -> x < 1000m) with 
                     | ContainsNegatives(negatives) -> raise (ArgumentException (buildExceptionMessage negatives))
                     | NoNegatives(digits)          -> digits |> Array.sum

If we convert that to use pattern matching we would get this:

let add value = match value with
                | "" -> 0.0m
                | "\n" -> 0.0m
                | value ->  match digits value |> Array.filter (fun x -> x < 1000m) with 
                            | ContainsNegatives(negatives) -> raise (ArgumentException (buildExceptionMessage negatives))
                            | NoNegatives(digits)          -> digits |> Array.sum

That’s maybe slightly easier to read mainly because of the splitting up of the two inputs which lead to a 0 result.

The final example of using if statements is the following bit of code:

let (|CustomDelimeter|NoCustomDelimeter|) (value:string) = 
	...
 
     if (value.Length > 2 && "//".Equals(value.Substring(0, 2))) then
         if ("[".Equals(value.Substring(2,1))) then CustomDelimeter(delimeters value)
         else CustomDelimeter([| value.Substring(2, value.IndexOf("\n") - 2) |])
     else NoCustomDelimeter(",")

The only way I could see how to make this use active patterns is on the boolean statements like so:

let (|CustomDelimeter|NoCustomDelimeter|) (value:string) = 
	...
 
    match (value.Length > 2 && "//".Equals(value.Substring(0, 2))) with
    | true -> match ("[".Equals(value.Substring(2,1))) with 
              | true  ->  CustomDelimeter(delimeters value)
              | false ->  CustomDelimeter([| value.Substring(2, value.IndexOf("\n") - 2) |])
    | false -> NoCustomDelimeter(",")

I quite like that it lines up the return values of the active pattern which seems to make it a bit more readable.

I think overall maybe the pattern matching versions are slightly more readable but maybe not by much. What do you think?

Written by Mark Needham

January 12th, 2010 at 1:33 am

Posted in F#

Tagged with

Roy Osherove’s TDD Kata: An F# attempt

with 5 comments

As I’ve mentioned in a few of my recent posts I’ve been having another go at Roy Osherove’s TDD Kata but this time in F#.

One thing I’ve been struggling with when coding in F# is working out how many intermediate variables we actually need. They can be useful for expressing intent better but they’re clutter in a way.

I’ve included my solution at the end and in the active pattern which determines whether or not we have a custom delimeter defined in our input string I can’t decide whether or not to create a value to represent the expressions that determine that.

3
4
5
6
7
8
9
10
    let (|CustomDelimeter|NoCustomDelimeter|) (value:string) = 
        ...
        let hasACustomDelimeter = value.Length > 2 && "//".Equals(value.Substring(0, 2))
 
        if (hasACustomDelimeter) then
            if ("[".Equals(value.Substring(2,1))) then CustomDelimeter(delimeters value)
            else CustomDelimeter([| value.Substring(2, value.IndexOf("\n") - 2) |])
        else NoCustomDelimeter(",")

In a way it’s quite obvious that the expression on line 3 is what we’re using to determine if the input string has a custom delimeter because we state that on the next line.

    let (|CustomDelimeter|NoCustomDelimeter|) (value:string) = 
        ...
        if (value.Length > 2 && "//".Equals(value.Substring(0, 2))) then
            if ("[".Equals(value.Substring(2,1))) then CustomDelimeter(delimeters value)
            else CustomDelimeter([| value.Substring(2, value.IndexOf("\n") - 2) |])
        else NoCustomDelimeter(",")

I can’t decide which I prefer so any thoughts on that would be welcome.

I ran into a bit of trouble trying to make the following requirement work because my original parse function was hiding the fact that the code was failing on this step:

Delimiters can be of any length with the following format:  ā€œ//[delimiter]\nā€ for example: ā€œ//***\n1***2***3ā€ should return 6

The parse function was originally defined to returns a zero value if it failed to parse the string which meant that the function which decomposed the string into a sequences of numbers could fail and we wouldn’t see an exception, just a failing test.

    let parse value = 
        let (itParsed, value) = Decimal.TryParse value
        if (itParsed) then value else 0.0m

Having the function defined like this simplified the code a bit because I didn’t need to deal with ignoring some characters at the beginning of the string when a custom delimeter was being specified.

One of the instructions for the exercise is to focus on writing tests for the valid inputs and not for invalid inputs which I initially struggled with. Usually if I was test driving code I would have written tests against invalid inputs to help me drive out the design.

Once I started focusing on just making the test past instead of finding a generic solution for the whole problem this became much easier and I didn’t need to test with the invalid inputs.

I wrote tests for the code in C# using NUnit so that I could run the tests from Resharper. I still haven’t found a good way to run automated tests from inside Visual Studio when they’re written in F# otherwise I’d have probably just done that.

All the tests I wrote were against the ‘add’ function but the way the code is written at the moment it would be possible to write tests against the other functions directly if I wanted to.

If I was working in C# perhaps some of those functions would be classes and I would write tests directly against those but I haven’t done that here and I’m not sure whether it is necessary. ‘digits’ is the only function where that would seem to add value.

This is the code I’ve got at the moment:

module FSharpCalculator
    open System
    open System.Text.RegularExpressions
 
    let split (delimeter:array<string>) (value:string) = value.Split (delimeter, StringSplitOptions.None)
    let toDecimal value = Decimal.Parse value
 
    let (|CustomDelimeter|NoCustomDelimeter|) (value:string) = 
        let delimeters (value:string) = Regex.Matches(value, "\[([^]]*)\]") |> Seq.cast |> 
                                        Seq.map (fun (x:Match) -> x.Groups) |>
                                        Seq.map (fun x -> x |> Seq.cast<Group> |> Seq.nth 1) |>
                                        Seq.map (fun x -> x.Value) |>
                                        Seq.to_array
 
        if (value.Length > 2 && "//".Equals(value.Substring(0, 2))) then
            if ("[".Equals(value.Substring(2,1))) then CustomDelimeter(delimeters value)
            else CustomDelimeter([| value.Substring(2, value.IndexOf("\n") - 2) |])
        else NoCustomDelimeter(",")    
 
    let digits value = match value with 
                       | CustomDelimeter(delimeters)  -> value.Substring(value.IndexOf("\n")) |> split delimeters  |> Array.map toDecimal 
                       | NoCustomDelimeter(delimeter) -> value.Replace("\n", delimeter) |> split [|delimeter |] |> Array.map toDecimal
 
    let buildExceptionMessage negatives = 
        sprintf "No negative numbers allowed. You provided %s" (String.Join(",", negatives |> Array.map (fun x -> x.ToString())))
 
    let (|ContainsNegatives|NoNegatives|) digits =
        if (digits |> Array.exists (fun x -> x < 0.0m)) 
        then ContainsNegatives(digits |> Array.filter (fun x -> x < 0.0m))
        else NoNegatives(digits)
 
    let add value = if ("".Equals(value) or "\n".Equals(value)) then 0.0m
                    else match digits value |> Array.filter (fun x -> x < 1000m) with 
                         | ContainsNegatives(negatives) -> raise (ArgumentException (buildExceptionMessage negatives))
                         | NoNegatives(digits)          -> digits |> Array.sum

Written by Mark Needham

January 10th, 2010 at 1:46 am

Posted in F#

Tagged with ,

F#: Refactoring to active patterns

with 3 comments

I’ve been playing around with more F# code and after realising that I’d peppered the code with if statements I thought it would be interesting to try and refactor it to make use of active patterns.

The code is part of my F# solution to Roy Osherove’s TDD Kata and is used to parse the input string and find which delimeters are being used.

This is the original code:

    let hasCustomDelimeter (value:string) = value.Length > 2 && "//".Equals(value.Substring(0, 2))
    let hasMultipleDelimeters (value:string) = hasCustomDelimeter value && "[".Equals(value.Substring(2,1))
 
    let delimeter value = if (hasCustomDelimeter value) then value.Substring(2, value.IndexOf("\n") - 2) else ","
    let delimeters (value:string) = Regex.Matches(value, "\[(.)\]") |> 
                                    Seq.cast |> 
                                    Seq.map (fun (x:Match) -> x.Groups) |>
                                    Seq.map (fun x -> x |> Seq.cast<Group> |> Seq.nth 1) |>
                                    Seq.map (fun x -> x.Value) |>
                                    Seq.to_array   
 
    let digits value = 
        let delimeter = delimeter value
        if (hasMultipleDelimeters value) then value.Substring(value.IndexOf("\n")) |> split (delimeters value) |> Array.map parse  
        else if (hasCustomDelimeter value) then value.Substring(value.IndexOf("\n")) |> split [| delimeter |] |> Array.map parse
        else value.Replace("\n", delimeter) |> split [|delimeter |] |> Array.map parse

The active pattern that we want to use is known as a ‘multi case active pattern’ which Chris Smith defines as “partitioning the entirety of the input space into different things”. In this case given an input string we want to determine what type of delimeters are contained within that string.

This is the code after I’d created the active pattern:

    let (|MultipleCustomDelimeters|SingleCustomDelimeter|NoCustomDelimeter|) (value:string) =  
        if (value.Length > 2 && "//".Equals(value.Substring(0, 2))) then
            if ("[".Equals(value.Substring(2,1))) then MultipleCustomDelimeters(delimeters value)
            else SingleCustomDelimeter(delimeter value)
        else NoCustomDelimeter(delimeter value)    
 
    let digits value =  
        match value with 
        | SingleCustomDelimeter(delimeter)     -> value.Substring(value.IndexOf("\n")) |> split [| delimeter |] |> Array.map parse
        | MultipleCustomDelimeters(delimeters) -> value.Substring(value.IndexOf("\n")) |> split delimeters  |> Array.map parse 
        | NoCustomDelimeter(delimeter)         -> value.Replace("\n", delimeter) |> split [|delimeter |] |> Array.map parse

One thing I didn’t realise is that you can set different types for the constructor values of each of the active patterns. In this case I want to match single or multiple delimeters and then return those delimeters. We can define one active pattern which matches a single delimeter and just returns that and then another one which returns an array of delimeters which is quite neat.

The way it works is quite similar to discriminated unions.

I found that that having all the code around parsing the input in the same function made it easier for me to understand that code and I quite like that it’s possible to match the pattern and also get the delimeter/delimeters in one expression.

Although there are more lines of code I think this code is more expressive and it wouldn’t be too hard to add in another active pattern if there’s another delimeter type that needs to be handled.

I can’t decide whether the ‘value.SubString’ and ‘value.Replace’ code should also be contained within the active pattern or not. At the moment I’m thinking perhaps not because it’s not related to the actual delimeters.

Written by Mark Needham

January 7th, 2010 at 11:31 pm

Posted in F#

Tagged with

F#: String.Split with a multi character delimeter

with one comment

In my continued efforts at Roy Osherove’s TDD Kata I’ve been trying to work out how to split a string based on a delimeter which contains more than one character.

My original thinking was that it should be possible to do so like this:

"1***2".Split("***".ToCharArray());;

I didn’t realise that splitting the string like that splits on each of the stars individually which means that we end up getting 2 empty values in the result:

val it : string [] = [|"1"; ""; ""; "2"|]

If we want to split on ‘***’ then we have to pass it in as a value in a string array:

"1***2".Split([| "***" |], StringSplitOptions.None);;

That way we only get the 1 and 2 which is what we want:

val it : string [] = [|"1"; "2"|]

I’d expected there to be an overload which takes in a string and then just splits on that but since there isn’t this isn’t a bad alternative.

Sam Allen has a very interesting article which covers all sorts of way to split different types of strings.

Written by Mark Needham

January 5th, 2010 at 11:10 pm

Posted in F#

Tagged with

F#: Expressing intent and the forward/application operators

with 5 comments

A while ago I wrote about F#’s forward and application operators where I’d looked at how these could be used to simplify code and while trying out Roy Osherove’s TDD Kata I realised that perhaps the choice of which of these to use or whether to use them at all depends on what intent we’re expressing.

The specific bit of code I was writing was for raising an exception if negative values were provided and I originally thought I’d use the forward operator to express this code:

    let digits = [| 1;2;3;-3 |] 
    let buildExceptionMessage negatives = sprintf "No negative numbers allowed. You provided %s" 
                                                  (String.Join(",", negatives |> Array.map (fun x -> x.ToString())))
 
    raise (ArgumentException (digits |> Array.filter (fun x -> x < 0) |> buildExceptionMessage))

I think in this case the forward operator doesn’t actually express the intent of the code better because it puts the focus on the digits rather than on the building of the exception message.

I changed that a bit to emphasise the importance of the ‘buildExceptionMessage’ function:

raise (ArgumentException (buildExceptionMessage (digits |> Array.filter (fun x -> x < 0))))

I thought it might be possible to get rid of the brackets around the filtering of the digits and instead apply that expression to ‘buildExceptionMessage’ using the application operator:

raise (ArgumentException (buildExceptionMessage <| digits |> Array.filter (fun x -> x < 0)))

That actually results in the following error message:

Type mismatch. Expecting a  string -> string but given a  'a array -> 'a array. The type 'string' does not match the type ''a array'

The problem is that it applies digits to ‘buildExceptionMessage’ first and then tries to apply the result of that to Array.filter instead of applying the filter to the digits and then passing the result of that calculation to ‘buildExceptionMessage’.

One way to get around this is to remove the forward operator and move digits to be the second argument passed to Array.filter instead:

raise (ArgumentException (buildExceptionMessage <| Array.filter (fun x -> x < 0) digits))

This is the version that I’ve got at the moment and I think it expresses the intent of the code the best.

I’d be interested in hearing more thoughts on the best way to use or not use these operators in idiomatic F# code.

Written by Mark Needham

January 4th, 2010 at 11:11 am

Posted in F#

Tagged with

F#: Word Count using a Dictionary

with 3 comments

Having spent some time unsuccessfully trying to make my F# attempt at the word count problem work I decided to follow the lead of the other examples I’ve read and make use of a Dictionary to keep count of the words.

I originally thought that I might be having a problem with the downloading of the files and storing of those strings in memory so I tried to change that bit of code to be lazily evaluated:

let downloadFile path = 
    lazy(use streamReader = new StreamReader(File.OpenRead path)
    streamReader.ReadToEnd())

That didn’t seem to make much difference though and it seemed like the StackOverflowException was happening on the ‘List.fold’ line:

let wordCount = files >> 
                List.map downloadFile >>
                List.map words >>
                List.fold (fun acc x -> Seq.append acc x) Seq.empty >> 
                Seq.groupBy (fun x -> x) >> 
                Seq.map (fun (value, sequence) -> (value, Seq.length sequence))

I couldn’t see a way of changing the solution such that the current approach wouldn’t need that line so I rewrote part of it ending up with the following solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#light
#r "FSharp.PowerPack"
open System
open System.IO
open System.Text.RegularExpressions
open System.Collections.Generic
 
let (|File|Directory|) path = if(Directory.Exists path) then Directory(path) else File(path)
let getFileSystemEntries path = Directory.GetFileSystemEntries path |> Array.to_list
 
let files path = 
    let rec inner fileSystemEntries files =
        match fileSystemEntries with
            | [] -> files
            | File path :: rest -> inner rest (path :: files)  
            | Directory path :: rest -> inner (List.append rest (getFileSystemEntries path)) files  
    inner (getFileSystemEntries path) []
 
let download path = using (new StreamReader(File.OpenRead path)) (fun reader -> reader.ReadToEnd())
let writeTo (path:string) f = using (new StreamWriter(path)) (fun writer -> f writer)
 
let words input = Regex.Matches(input, "\w+") |> Seq.cast |> Seq.map (fun (x:Match) -> x.Value.ToLower()) 
let apply (dict:Dictionary<string,int>) key f = if(dict.ContainsKey(key)) then dict.[key] <- f dict.[key] else dict.[key] <- f 0
 
let startTime = DateTime.Now
let dict = new Dictionary<string, int>()
 
files "Z:\\20_newsgroups" |> List.iter (fun file -> download file |> words |> Seq.iter (fun word -> apply dict word ((+) 1) )) 
 
printfn "Writing counts in alphabetical order"
writeTo "C:\\results\\counts-alphabetical-fsharp.txt" (fun out -> 
    dict |> Seq.sortBy (fun x -> x.Key) |> Seq.iter (fun entry -> out.WriteLine(entry.Key + " " + entry.Value.ToString())))
 
printfn "Writing counts in descending order"
writeTo "C:\\results\\counts-descending-fsharp.txt" (fun out -> 
    dict |> Seq.sortBy (fun x -> x.Value * -1) |> Seq.iter (fun entry -> out.WriteLine(entry.Key + " " + entry.Value.ToString())))
 
let endTime = DateTime.Now
printfn "Finished in: %d seconds" (endTime - startTime  ).Seconds

As I wrote about previously I found out that I could use the ‘using’ function instead of the ‘use’ keyword with the ‘StreamWriter’ and ‘StreamReader’ so those bits of code are a bit simplified.

The way of interacting with dictionaries in F# doesn’t seem as nice as in Ruby so I’ve ended up with the somewhat verbose bit of code on line 23. Is there a cleaner way of doing that?

By using a Dictionary I think it’s now more difficult to parallelise the counting up of the words which was something I thought might be possible when I first came across the problem.

This seems like the perfect problem for the MapReduce approach although I’m not quite sure about the implementation details.

My thinking is that we’d have a Dictionary for each node/actor and it would sum up the words in its file before passing the result to another actor which would be responsible for taking all the dictionaries and accumulating the word counts?

This was an interesting problem for showing what happens if you try to store too much data in memory and it’s something that I’ve not come across before because I don’t typically work with data sets that are this big.

Written by Mark Needham

December 20th, 2009 at 10:09 am

Posted in F#

Tagged with

F#: The use keyword and using function

without comments

While I was playing around with the little F# script that I wrote to try and solve the word count problem I noticed that in a couple of places I had used the ‘use‘ keyword when dealing with resources that needed to be released when they’d been used.

Using the ‘use’ keyword means that the ‘Dispose’ method will be called on the resource when it goes out of scope.

The two examples were ‘StreamWriter’ and ‘StreamReader’:

let writeTo (path:string) f = 
    use writer = new StreamWriter(path)
    f writer
let download path = 
    use streamReader = new StreamReader(File.OpenRead path)
    streamReader.ReadToEnd()

I found it quite annoying that those bits of code needed to take up three lines despite the fact I don’t really need to have the class construction assigned.

Luckily there is a ‘using’ function available which allows us to make these bits of code more concise.

‘using’ takes in 2 arguments – the object to be created and a function which takes in that object and does something with it.

If we make use of that function instead of the ‘use’ keyword we end up with the following function definitions:

let writeTo (path:string) f = using (new StreamWriter(path)) (fun writer -> f writer)
let download path = using (new StreamReader(File.OpenRead path)) (fun reader -> reader.ReadToEnd())

When we’re just doing one thing with the resource, as I am here, then I think this reads better. If we’re using it for multiple different operations then perhaps the use keyword is more appropriate.

Written by Mark Needham

December 19th, 2009 at 10:33 am

Posted in F#

Tagged with

F#: Word Count – A somewhat failed attempt

with 2 comments

I came across Zach Cox’s word count problem via Sam Aaron and Ola Bini’s twitter streams and I thought it’d be interesting to try it out in F# to see what the solution would be like.

The solution needs to count word frequencies from a selection of newsgroup articles.

I wanted to see if it was possible to write it in F# without using a map to keep track of how many of each word had been found.

My thinking was that I would need to keep all of the words found and then calculate the totals at the end.

After a bit of fiddling this is the version I ended up with:

word-count.fsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#light
open System
open System.IO
open System.Text.RegularExpressions
 
let (|File|Directory|) path = if(Directory.Exists path) then Directory(path) else File(path)
let getFileSystemEntries path = Directory.GetFileSystemEntries path |> Array.to_list
 
let files path = 
    let rec inner fileSystemEntries files =
        match fileSystemEntries with
            | [] -> files
            | File path :: rest -> inner rest (path :: files)  
            | Directory path :: rest -> inner (List.append rest (getFileSystemEntries path)) files  
    inner (getFileSystemEntries path) []
 
let downloadFile path = 
    use streamReader = new StreamReader(File.OpenRead path)
    streamReader.ReadToEnd()    
 
let words input= Regex.Matches(input, "\w+") |> Seq.cast |> Seq.map (fun (x:Match) -> x.Value.ToLower())
 
let wordCount = files >> 
                List.map downloadFile >>
                List.map words >>
                List.fold (fun acc x -> Seq.append acc x) Seq.empty >> 
                Seq.groupBy (fun x -> x) >> 
                Seq.map (fun (value, sequence) -> (value, Seq.length sequence))
 
let writeTo (path:string) (values:seq<string * int>) = 
    use writer = new StreamWriter(path)
    values |> Seq.iter (fun (value,count) -> writer.WriteLine(value + " " + count.ToString()))  
 
let startTime = DateTime.Now
let count = wordCount "Z:\\20_newsgroups"
 
printfn "Writing counts in alphabetical order"
count |> Seq.sort |> writeTo "C:\\results\\counts-alphabetical-fsharp.txt"
 
printfn "Writing counts in descending order"
count |> Seq.sortBy (fun (_, count) -> count * -1) |> writeTo "C:\\results\\counts-descending-fsharp.txt"
 
let endTime = DateTime.Now
printfn "Finished in: %d seconds" (endTime - startTime).Seconds

The problem is that this version results in a StackOverFlow exception when I try to execute it with all the newsgroup articles although it does work correctly if I select just one of the folders.

From what I can tell the exception happens on line 24 when I get the text out of each of the files and store it in the list.

I tried changing this bit of code so that instead of doing that I combined the ‘words’ and ‘downloadFile’ functions so that the whole string wouldn’t be saved but this doesn’t seem to help that much. The exception just ended up happening a bit further down.

I’m not sure if it’s possible to make this work by making use of lazy collections – I’m not that familiar with those yet so I”m not sure how to do it – or if this approach is just doomed!

Despite the fact it doesn’t quite work there were some interesting things I noticed while playing with this problem:

  • At one stage I was trying to deal with a list of sequences whereby I had a list of sequences of words for each of the newsgroup articles. I found this really difficult to reason about as I was writing a ‘List.map’ and then a ‘Seq.map’ inside that.

    I originally had the ‘List.fold (fun acc x -> Seq.append acc x) Seq.empty’ line happening later on in that composition of functions such that I grouped all the words and then counted how many there were before folding down into a single sequence.

    I realised this didn’t make much sense and it would be much easier to just go to the sequence earlier on and make the code easier to follow.

  • I’ve previously written about wrapping .NET library calls and I was doing this quite a lot when I started writing this code.

    For example I had written a function called ‘isDirectory’ which wrapped ‘Directory.Exists’ which I wrote more out of habit than anything else but it doesn’t really add much value. I think when we’re talking about wrapping static methods this is probably always the case. It’s when we want to call a method on a C# object that the wrapping approach can be helpful.

  • I quite like the Ruby way of writing to a file…
    open("counts-descreasing-ruby", "w") do |out|
      counts.sort { |a, b| b[1] <=> a[1] }.each { |pair| out << "#{pair[0]}\t#{pair[1]}\n" }
    end

    …so I thought I’d see what it would look like to change my ‘writeTo’ function to be more like that:

    let writeTo (path:string) (f: StreamWriter -> Unit) = 
        use writer = new StreamWriter(path)
        f writer
    writeTo "C:\\results\\counts-alphabetical-fsharp.txt" (fun out -> 
        count |> Seq.sort |> Seq.iter (fun (v,c) -> out.WriteLine(v + " " + c.ToString())))

    I’m not sure it reads as well as the original version – the writing to file seems to becomes more prominent in this version than the data being written to it.

If anyone has any ideas about how I can get this not to blow up that would be cool!

These are some of the other solutions that I’ve come across:

Written by Mark Needham

December 18th, 2009 at 2:58 am

Posted in F#

Tagged with

Haskell vs F#: Function composition

with 11 comments

I’m reading through John Hughes’ ‘Why functional programming matters‘ paper and one thing I’ve come across which is a bit counter intuitive to me is the Haskell function composition operator.

I’ve written previously about F#’s function composition operator which is defined as follows:

let inline (>>) f g x = g(f x)

To write a function which doubled all the values in a list and then returned the odd values we’d do this:

let doubleThenOdd = List.map (fun x -> x*2) >> List.filter (fun x -> x % 2 <> 0)

Of course it’s not possible for there to be any values!

doubleThenOdd [1..5];;
val it : int list = []

Based on that understanding I would expect the Haskell function composition operator (‘.’) to work in the same way:

let doubleThenOdd = map (\ x -> x*2) . filter (\ x -> (mod x 2) /= 0)

But it doesn’t!

Prelude> doubleThenOdd [1..5]
[2,6,10]

In Haskell the functions are applied from right to left rather than left to right as I had expected.

The definition of ‘.’ is therefore:

(f . g) x = f (g x)

So to get what I wanted we’d need to switch around ‘map’ and ‘filter’:

let doubleThenOdd = filter (\ x -> (mod x 2) /= 0) . map (\ x -> x*2)
Prelude> doubleThenOdd [1..5]
[]

It’s not too difficult to follow once I worked out that it was different to what I was used to but I was very confused for a while!

Is there a reason why they implement this operator differently?

Written by Mark Needham

December 9th, 2009 at 10:10 pm

Posted in F#

Tagged with ,

F#: Playing around with asynchronous workflows

with 2 comments

I spent a bit of time over the weekend playing around with F# asynchronous workflows and seeing how they could be used to launch Firefox windows asynchronously for my FeedBurner graph creator.

Initially I decided to try out the ‘Async.RunWithContinuations’ function which I recently read about on Matthew Podwysocki’s blog.

Matthew describes this as being a function which is useful for executing a single operation asynchronously and this worked out quite well for me as my application only has the ability to get one feed and then create a graph from its data.

I changed the Execute function (which takes in arguments from the command line as I wrote about previously) to launch a firefox window with the graph loaded:

let launchInFirefox url = async { System.Diagnostics.Process.Start(@"C:\Program Files\Mozilla Firefox\firefox.exe", url) |> ignore }
 
let timeNow () = System.DateTime.Now.ToLongTimeString()
 
let Execute args =    
    if (Array.length args <> 3) 
    then printfn "Expected usage: [feedName] [startDate yyyy-mm-dd] [endDate yyyy-mm-dd]" 
    else 
        let feedName, startDate, endDate = args.[0], args.[1], args.[2]
        let graphUri = (ShowFeedBurnerStats feedName startDate endDate).AbsoluteUri
 
        Async.RunWithContinuations ( (fun cont -> printfn "Downloaded feed graph for %s at %s" feedName (timeNow())), 
                                     (fun ex -> printfn "Failed to download feed graph for %s - %s %s " feedName (ex.Message) (ex.StackTrace)), 
                                     (fun cancelled -> printfn "Feed graph downloading for %s was cancelled" feedName),
                                     (launchInFirefox graphUri) )

The function actually takes in three continuations as well as the asynchronous computation to run:

  • A continuation to run if the computation completes successfully
  • An exception continuation to run if the computation throws an exception. I was able to test this out by trying to launch a process which did not exist
  • A cancellation continuation to run if there is a signal for the computation to be cancelled

We then pass in the asynchronous computation as the last argument to the function which in this case is a process which launches FireFox with the url of the graph.

This works quite nicely but you don’t really notice that much different between launching the browser this way and just doing it using the ‘Async.RunSynchronously’ function.

It becomes a bit more interesting if we try to execute more than one asynchronous computations which in this case means creating multiple graphs at the same time.

My first attempt was to launch each of these computations synchronously:

let CreateGraphs (feeds:seq<string>) =
    feeds |> 
    Seq.map (fun f -> ShowFeedBurnerStats f "2009-03-01" "2009-07-25") |>
    Seq.map (fun uri -> launchInFirefox uri.AbsoluteUri ) |> 
    Seq.iter (Async.RunSynchronously)

I called this function like so:

let feeds = seq { yield "markneedham"; yield "scotthanselman"; yield "codethinked"; yield "haacked"; yield "Iserializable" };
CreateGraphs feeds

That works fine although there is a noticeable pause as each of these is loaded into the browser one after the other.

One way to get around this is to make use of the ‘Async.Parallel’ function which converts a sequence of asynchronous computations into a single asynchronous computation which can execute all of the individual asynchronous computations.

I initially got confused here and thought that passing a sequence of asynchronous computations to ‘Async.Parallel’ actually executed them but as I learnt you actually need to pass the result to one of the functions which actually runs the asynchronous computations.

We don’t need to change our function too much to achieve this:

let CreateGraphsParallel (feeds:seq<string>) =
    feeds |> 
    Seq.map (fun f -> ShowFeedBurnerStats f "2009-03-01" "2009-07-25") |>
    Seq.map (fun uri -> launchInFirefox uri.AbsoluteUri ) |> 
    Async.Parallel |>
    Async.RunSynchronously
let feeds = seq { yield "markneedham"; yield "scotthanselman"; yield "codethinked"; yield "haacked"; yield "Iserializable" };
CreateGraphsParallel feeds

The graphs seem to get launched in FireFox much more quickly using this method and there is no real pause, just a flurry of new tabs being launched as each of the graphs is opened.

I thought the ‘Async.Start’ function might allow us to achieve a similar result as the API comments state ‘Start the asynchronous computation in the thread pool. Do not await its result’ but I saw similar behaviour to when I used ‘Async.RunSynchronously’

let CreateGraphsSpawn (feeds:seq<string>) =
    feeds |> 
    Seq.map (fun f -> ShowFeedBurnerStats f "2009-03-01" "2009-07-25") |>
    Seq.map (fun uri -> launchInFirefox uri.AbsoluteUri ) |> 
    Seq.iter(Async.Start)
let feeds = seq { yield "markneedham"; yield "scotthanselman"; yield "codethinked"; yield "haacked"; yield "Iserializable" };
CreateGraphsSpawn feeds

Out of these ‘Async.Parallel’ seems to be the best function to use to get quick feedback from multiple computations.

There are also a few other functions that I haven’t tried out yet and I’m intrigued as to whether we would achieve good results by making use of MailBoxProcessors or not.

Written by Mark Needham

July 26th, 2009 at 11:45 pm

Posted in F#

Tagged with ,