Search code examples
f#idioms

Idiomatic F# - Simple Statistical Functions


As part of a simple challenge I am to write a couple of simple statistical functions by scratch and I'm trying to write them in the most "idiomatic F#" way possible. I am fairly new to Functional Programming so I'm looking to learn how to create simple stuff from the start.

Here's what I have so far:

let mean (x : float list) : float =
    (List.sum x) / (float (List.length x))

let variance (x : float list) : float =
    x
    |> List.map (fun a -> pown (a - (mean x)) 2)
    |> mean

let stdDev =
    variance >> Math.Sqrt

I like how the stdDev function is defined using composition but I get the feeling there might be some prettier, more idiomatic way of defining the first two.

Any suggestions?


Solution

  • Your code is perfectly fine and idiomatic.

    Personally, I prefer one liners whenever possible. That way I can align the code to highlight similarities and differences between the functions. Patterns just jump at you that way.

    let mean     x = (Seq.sum x) / (float (Seq.length x))
    let variance x = let m = mean x
                     x |> Seq.map (fun a -> pown (a - m) 2) |> mean
    let stdDev   x = x |> variance |> Math.Sqrt
    

    I also prefer seq to list because they can be used with lists, arrays, sets or any other sequence.

    do  [| 5. ; 6. ; 7. |] |> stdDev |> printfn "%A"
    do  [  5. ; 6. ; 7.  ] |> stdDev |> printfn "%A"    
    Set [  5. ; 6. ; 7.  ] |> stdDev |> printfn "%A"
    seq [  5. ; 6. ; 7.  ] |> stdDev |> printfn "%A"        
    seq {  5.   ..   7.  } |> stdDev |> printfn "%A"        
    

    In F# is better to avoid the >> composition operator and use the pipe |> instead. There are many issues with composing functions like that. For instance the above code would not be possible (using different types like lists and arrays).