Search code examples
filterf#setseq

F#: how to calculate a subset using filtering predicate?


E.g. For integer numbers between 1 and 10, select 3 numbers that:

1. Sum of these 3 numbers equals to 24
2. These 3 numbers could build a right triangle.

How to use F# to get these 3 numbers? I know for Haskell this is very simple:

Prelude> let rightTriangle=[(a,b,c)|c<-[1..10],a<-[1..c],b<-[1..a],a^2+b^2==c^2,a+b+c==24]
Prelude> rightTriangle

The solution is

[(8,6,10)]

I'm not sure if

F# could help to generate a Cartesian product conveniently?
F# could add different filter conditions inside one expression?

So, how to implement it with F# conveniently? Thanks.


Solution

  • The direct equivalent of the Haskell version in F# would be to use list comprehensions:

    let rightTriangle=
      [for c in 1 .. 10 do
       for a in 1 .. c do
       for b in 1 .. a do
         if pown a 2 + pown b 2 = pown c 2 && a + b + c = 24 then
           yield a, b, c ]
    

    Generally speaking, F# comprehensions are closer to "normal F# language" rather than being a special language feature (if you drop the [ .. ] around it, it looks almost like imperative iteration using loops).

    • The for construct corresponds to a <- 1 .. 10, but you need to nest multiple fors if you want to bind multiple variables
    • The if construct corresponds to the filtering using the == bit in Haskell
    • The yield specifies what values should be returned from the list comprehension