orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1]
orElse[A1 >: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1]
val fun1 = {
case x : Int => x + 1
case d : Double => (d + 1).toInt
}
val fun2 = {
case d : Double => (d + 1).toInt
case s : String => s.length
}
val fun3 = {
case x : Int => x + 1
case s : String => s.length
}
val i = { case x : Int => x + 1 }
val d = { case d : Double => (d + 1).toInt }
val s = { case s : String => s.length }
val fun1 = i orElse d
val fun2 = d orElse s
val fun3 = i orElse s
Most scala type abstractions seems natural. co/contra variance forms consistent theory. But I could not make myself belive in the PartialFunction[-R,+T]. Why -R ? PartialFunction looks like it is univariant. Suppose you get A <: B <: C. You may easily pass (c : C) to a PartialFunction[B,T] as for any other function.
scala> def test[C, B <: C, A <: B, T](pf: PartialFunction[B, T], c: C) =
| pf(c)
<console>:12: error: type mismatch;
found : c.type (with underlying type C)
required: B
pf(c)
^
scala> def test[C, B <: C, A <: B, T](pf: PartialFunction[B, T], a: A) =
| pf(a)
test: [C, B <: C, A <: B, T](pf: PartialFunction[B,T], a: A)T
But you could as easily pass (a : A) to the same function, it would be matched during runtime and if neither of case clauses is triggered, than there is just no match. <snip>
So I have several questions. Have I missed something in partial function nature?
I feel that the problem is not with the partial functions themself but with scala representation for them and it is a matter of the platform representation. Have I guessed right? If yes than there should exist clear description of the concept independent from specific language.
Just as A -> B says that A is the type of arguments the function is capable of handling, for PF, T is the type of arguments that the PF is capable of discriminating among.
Suppose you have a computer vision system on an assembly line; it
recognizes parts of an assembled machine and checks how close they
are to spec, classifying the machine, accept, reject, adjust,
&c. And then a cat walks into the camera view. Is it
meaningful to ask for the vision system's classification of the
cat? Not really.
This model gives you a tool to say either "yes" if desirable (via
setting T = the top type), but usually the answer is "no",
and that is modeled by choosing an appropriate T, which is
below the top type. So the presence of T in the
type model lets you more precisely model what you mean, i.e. ban
the cats from the assembly floor.
You have described PartialFunction as container for the isDefinedAt and the apply methods. Looking at their signature, you really could tell, that there should be contravariant R type signature. But what if look at partial function as container for case clauses?
trait PF[-T, +R] {self => type M val discriminate: T => Option[M] val complete: M => R def orElse[TT <: T, RR >: R](o: PF[TT, RR]): PF[TT, RR] = new PF[TT, RR] { type M = Either[self.M, o.M] override val discriminate = ??? override val complete = ??? } }
More intuitively, but by no means replacing the above discussion, a single case clause is still a specialization of PF. A List[T => R] still puts T in contravariant position, however the underlying contravariant position comes about.