hqt
hqt

Reputation: 30284

How to use List.filter?

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

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

But when compile, I always receive error :

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

What does this error mean? How to fix it?

Upvotes: 9

Views: 15060

Answers (5)

Dyslexic Dogo
Dyslexic Dogo

Reputation: 11

In the SML document, the filter function in the List structure listed as

filter f l

where it takes curried arguments f and l

Instead of passing the arguments in a tuple, you have to provide a function and the list separated by spaces. The answer will be like this

fun only_capitals (xs: string list) = 
    List.filter (fn s => Char.isUpper(String.sub(s,0))) xs

Upvotes: 1

Russell.Luo
Russell.Luo

Reputation: 79

In the SML document, it states that:

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

So it is a curried function.

Upvotes: 3

irudyak
irudyak

Reputation: 2341

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

List.filter is so called curried function, so List.filter f xs is actually (List.filter f) xs where List.filter f is a function. We have to 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 its 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

Upvotes: 5

pad
pad

Reputation: 41290

Type signature of List.filter is

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

So you need to give List.filter two distinct arguments, not one argument which happens to be a tuple.

Upvotes: 16

Faiz
Faiz

Reputation: 16265

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's easy to confuse syntax of passing a tuple in ML with the sytax of functional application in other languages.

You could also define it as:

val only_capitals = List.filter f

Upvotes: 8

Related Questions