tags:

views:

78

answers:

2

The following compiles just fine using scala Beta1 and scalaz snapshot 5.0:

val p1: Int => Boolean = (i : Int) => i > 4

val s: List[Int] = List(1, 2, 3)
val b1 = s ∃ p1

And yet this does not:

val s: Set[Int] = Set(1, 2, 3)
val b1 = s ∃ p1

I get the following error:

Found: Int => Boolean
Required: Boolean => Boolean

The signature of the ∃ method is:

def ∃(p: A => Boolean)(implicit r: FoldRight[M]): Boolean = any(p)

And there should be an implicit SetFoldRight in scope. It is exactly the same for the methods: ∀, ∋ and ∈: - what is going on?

+3  A: 

It looks like the A in MA[M[_],A] is Boolean for a Set. In the Scalaz object, there is the following implicit:

implicit def Function1ApplyMA[A, R](f: A => R): MA[PartialApply1Of2[Function1, A]#Apply, R] = ma[PartialApply1Of2[Function1, A]#Apply, R](f)

Now I don't fully understand what's going on with the types here, but it looks like the A in MA[M[_],A] is the return type of the Function1. Set[A] extends A => Boolean, hence why A in the definition of ∃ is being inferred to Boolean.

One fix is to use the explicit ma method to convert the Set into an MA, rather than let implicits do the heavy lifting:

val s = ma(Set(1, 2, 3))
Ben Lings
I see - I knew it was something to do with the fact that Set extends `A => Boolean`. The implicit you specify creates an `MA[M[_], A]` from a `Function`[I, R]`. `M[_]` is inferred as the `PartialApply1Of2` which makes the second type argument to `MA` be `R`. `R` is of course the return type of the `Function1` which is `Boolean` in this case.
oxbow_lakes
+2  A: 

I need to add this to object Scalaz:

implicit def SetMA[M[_] <: Set[_], A](s: M[A]): MA[M, A] = ma[M, A](s)

But, thanks to #2741, I'm running into a problem making this higher priority than the offending conversion:

implicit def Function1ApplyMA[A, R](f: A => R): MA[PartialApply1Of2[Function1, A]#Apply, R]  = ma[PartialApply1Of2[Function1, A]#Apply, R](f)

I really wish that Seq and Set were implicitly convertible to Function1 rather than inheriting from it.

UPDATE

This is now fixed.

retronym
I think that there should also be a "cleaner" Set-based implementation for the member methods - i.e. that they do not use `FoldRight` but rather use the fact that a `Set` is a `A => Boolean`. Not that I have any idea how to do this :-)
oxbow_lakes