Of Code and Me

Somewhere to write down all the stuff I'm going to forget and then need

F# warning FS0020: October 31, 2008

Filed under: Uncategorized — Rupert Bates @ 10:27 pm
Tags:

Something interesting I found out today:

I’ve seen this warning quite a lot when programming in F:

“warning FS0020: This expression should have type ‘unit’, but has type ‘SomeType’.”

for instance in something I was coding today:

let CreateDirectory d =
    printfn "creating directory %s" d
    Directory.CreateDirectory (destDir + d) //warning FS0020
    () //this function has to return unit in order to be used with Array.iter

Array.iter CreateDirectory dirs

The way to get rid of this warning is to pipeline the result of the function which is causing the warning into the ignore function as follows:

Directory.CreateDirectory (destDir + d) |> ignore

and hey presto your warning disappears.

Advertisements
 

Exploring F#, active patterns, refactoring, rambling… October 24, 2008

Filed under: Uncategorized — Rupert Bates @ 7:11 pm
Tags: , , ,

I’ve spent some of today playing around with F# and here are the results:

I am working on a little app that takes a list of numbers does various things with them and then plots the results on a chart using the Google Charts API.
To do this I need to take an F# list of ints and convert it to a comma delimited string.

Now, if anyone knows of a library function that does this, then great, thanks, let me know and I’ll use it next time, but this time it seemed like a good opportunity to try to think about algorithms in a more functional way.

So, if I was doing this in C# I’d write something like:

    string s = "";
    foreach(int i in list)
    {
        s += i + ",";
    }
    return s.TrimEnd(',');

But entering into the spirit of functional programming I want to try to avoid loops and mutable state so came up with this:

let rec listAsString (l : int list) =
    match l with
        |[] -> ""
        |head::tail  ->
            if List.length tail = 1 then string tail.[0]
            else string head + "," +  listAsString tail

No mutable state, uses recursion rather than loops, great, I’m feeling pretty smug. But… that if statement looks a bit ugly, so I thought I’d see if I could find a more elegant solution.

So then I dug out a blog post by Chris Smith on active patterns and that seemed like a good solution.

So I wrote an active pattern to match the 3 states of the list that I’m interested in (empty, one element left, more than one character left)

    let (|MoreThanOne|LastElement|EmptyList|)(l : int list) =
    if List.length l = 0 then
        EmptyList
    elif List.length l = 1 then
        LastElement(List.hd l)
    else
        let head::tail = l
        MoreThanOne(head, tail)

And this lets me amend my function as follows:

    let rec listAsString (l : int list) =
    match l with
        |EmptyList -> ""
        |MoreThanOne(head, tail) -> string head + "," +  listAsString tail
        |LastElement x -> string x

Which seems both concise and readable.

Then I realised that actually I could do the same thing with a lot less code as follows:

let listAsString(l: int list) =
    List.fold_left (fun acc i -> acc + string i + ",") "" l
    |> fun s -> s.TrimEnd [|','|]

That is one of the things I’m enjoying about F#, there always seem to be a number of different approaches to any problem.