Question

Let's say I have a discriminated union:

type foo = Bar | Baz | Batz

Then, I want to check how many members of a list are of type Baz:

List.sumBy (function Bar -> 1 | _ -> 0) foos

Is there a more idiomatic way to do this?

Was it helpful?

Solution

Notice that your example is incorrect. It should be:

List.sumBy (fun x -> match x with Baz -> 1 | _ -> 0) foos

which could be rewritten as:

List.sumBy (function Baz -> 1 | _ -> 0) foos

I don't think there's a more idomatic way than using List.sumBy here.

OTHER TIPS

It depends on how would you define "more idiomatic". If it is a synonym of language proficiency measured, among other factors, by code performance, then similarly terse

List.fold (fun sum -> function Baz -> sum + 1 | _ -> sum) 0 foos

may be considered more idiomatic as it executes 3-4 times faster, than version with List.sumBy under F# 2.0.

Performance disparity that much significant has place because implementation of List.fold is highly optimized specifically for lists, while List.sumBy falls back to Seq.sumBy where implementation goes through ordinary IEnumerable traversal.

I would define a count function. It's a pretty common use case to want to count the number of elements that satisfy the given predicate.

let count pred = List.sumBy (fun x -> if pred x then 1 else 0)

Use:

count (fun x -> x = Bar) foos

This is what I'd have done instinctively. Filter |> Length seems more natural than summing or folding. Haven't checked peformance.

let count = 
    myList 
        |> List.filter (fun elem -> match elem with | Baz -> true | _ -> false)
        |> List.length

...and for completenesss, don't forget the little-known fact that for-loops can pattern match. You will get a warning about incomplete pattern matching, though, which is annoying.

open System

type foo = Bar | Baz of int | Batz of string * string

let myList = [Bar; Bar; Baz(1); Batz("x", "y"); Baz(2)]

let count = 
    let mutable acc = 0
    for Baz(_) in myList do
        acc <- acc + 1
acc
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top