Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# filter function - first argument's condition seems to be reversed

I have a little weird experience with F# filter function today. The code is:

let rec filter : ('a -> bool) -> 'a list -> 'a list =
    fun isKept -> function
        | [] -> []
        | (x::xs) -> if isKept x then x::filter isKept xs
                     else filter isKept xs

let x = filter ((>) 1) [1; -5; -20; 30; -35; 40]

That code returns

val x : int list = [-5; -20; -35]

Problem is, as I pass a condition in the first argument (> 1), I expect it would filter out any list elements of the second argument that are greater 1, not the reverse.

Is there anything obviously clear that I couldn't spot?

like image 875
user2431438 Avatar asked Sep 07 '13 13:09

user2431438


1 Answers

Your filter function is fine. The problem is that this line of code:

let x = filter ((>) 1) [1; -5; -20; 30; -35; 40]

Is equivalent to this code if you use an explicit lambda instead of partially applying the (>) operator:

let x = filter (fun x -> 1 > x) [1; -5; -20; 30; -35; 40]

The reason for this is that the (>) function takes two arguments; even though the 1 appears to the right of the (>), it's not passed as the "right" argument to the function. The solution is to either use (<) instead:

> let x = filter ((<) 1) [1; -5; -20; 30; -35; 40];;

val x : int list = [30; 40]

or to use an explicit lambda function to ensure you apply the arguments in the correct order:

> let x = filter (fun x -> x > 1) [1; -5; -20; 30; -35; 40];;

val x : int list = [30; 40]
like image 103
Jack P. Avatar answered Oct 01 '22 03:10

Jack P.