SML: how to use List.filter

I have this code to filter a list of strings that the first letter is the capital:

fun fs = Char.isUpper(String.sub(s,0)); fun only_capitals (xs : string list) = List.filter(f , xs); 

But when compiling, I always get an error:

 operator domain: 'Z -> bool operand: (string -> bool) * string list in expression: List.filter (f,xs) 

I do not know how to fix this. You can tell what this error means and how to fix it.

Thanks:)

+4
source share
4 answers

The typical signature of List.filter is

 val filter : ('a -> bool) -> 'a list -> 'a list 

So you need to give List.filter two different arguments, not one argument, which is a tuple.

+11
source

You need to change it to:

 fun only_capitals (xs : string list) = List.filter f xs 

filter takes 2 arguments, a function f ( 'a -> bool ) and a list.

It is easy to confuse the syntax for transferring a tuple to ML using the sytax functional application in other languages.

You can also define it as:

 val only_capitals = List.filter f 
+4
source

Functions in ML can only take one argument. Description from here (see also notes and videos).

List.filter is a so-called curry function, so List.filter f xs is actually (List.filter f) xs , where List.filter f is a function. We should provide f (fn: a -> bool) as an argument to List.filter , not tuple (f, xs) .

Here is a simple example. When we call is_sorted 1 , we get a closure with x in our environment. When we call this closure with 2, we get true because 1 <= 2 .

 val is_sorted = fn x => (fn y => x <= y) val test0 = (is_sorted 1) 2 val is_sorted = fn : int -> int -> bool val test0 = true : bool 
+2
source

The SML document states that:

the fl filter applies f to each element x of l, from left to right, and returns a list of those x for which fx evaluates to true, in the same order in which they occurred in the argument list.

So this is a curry function.

0
source

All Articles