LogicProgrammer
LogicProgrammer

Reputation: 77

Type mismatch in Scala(filter function)

I am new to Scala and try to focus on more functional programming side of it.

I am trying to write a function filter.

Here is a definition and implementation:

def filter[A, B](f: A => Boolean, l: List[A]): List[B] = l match {
    case Nil => List()
    case x :: xs => if (f(x)) (x: B) :: filter(f, xs) else filter(f, xs)
}

Using this function, I get this error: :32: error: type mismatch;

 found   : x.type (with underlying type A)
 required: B
           case x :: xs => if (f(x)) (x: B) :: filter(f, xs) else filter(f, xs)

Now, before that I wrote a function map:

def map[A, B](f: A => B, l: List[A]): List[B] = l match {
    case Nil => List()
    case x :: xs => f(x) :: map(f, xs)
}

that actually applies function f to convert each list element from type A to type B.

My error for filter seems to be caused by the fact that function taken by filter does nothing to list element x of type A, so type checker thinks that I am still building a list of type A when B is required. You can see I tried to specify x as type B but it was in vain. Can anyone confirm that I understood problem correctly and how can I make x as type B? I could just return list of type A but this is a function definition that is given as an exercise and I cannot change it.

Upvotes: 2

Views: 1715

Answers (1)

Archeg
Archeg

Reputation: 8462

Your filter method seems to try converting A to B which is not what filter methods usually do. A and B are two unrelated types, so you cannot cast between them

You would want something like that:

def filter[A](l: List[A])(f: A => Boolean): List[A] = l match {
    case Nil => List()
    case x :: xs => if (f(x)) x :: filter(xs)(f) else filter(xs)(f)
}

But you also can write this one a bit simpler:

def filter[A](l: List[A])(f: A => Boolean): List[A] =
    for (x <- l if f(x)) yield x

Please also notice that I have swapped the arguments and divided them. This is done in order for scala's type inference to infer A automatically. Now you can do this:

filter(List(1, 3, 5, 7))(_ > 4)

where Int type is infered implicitly

Upvotes: 2

Related Questions