Scala PartialFunctions from concrete ones
Is there any quick way to use as a concrete function (of type, say, (A) => B
) as a PartialFunction[A, B]
? The most concise syntax I know of is:
(a: A) => a match { case o开发者_StackOverflow社区bj => func(obj) }
Is there an implicit conversion anywhere, something like:
implicit def funcAsPartial[A, B](func: A => B) = new PartialFunction[A, B] {
def isDefinedAt(a: A) = true
def apply(a: A) = func(a)
}
I guess I just wrote what I was looking for, but does this already exist in the Scala libraries?
Doing this with an implicit conversion is dangerous, for the same reason that (A) => B
should not inherit from PartialFunction[A, B]
. That is, the contract of PartialFunction guarantees that you can safely* call apply
wherever isDefinedAt
returns true
. Function1's contract provides no such guarantee.
Your implicit conversion will result in a PartialFunction that violates its contract if you apply it to a function that is not defined everywhere. Instead, use a pimp to make the conversion explicit:
implicit def funcAsPartial[A, B](f: A => B) = new {
/** only use if `f` is defined everywhere */
def asPartial(): PartialFunction[A, B] = {
case a => f(a)
}
def asPartial(isDefinedAt: A => Boolean): PartialFunction[A, B] = {
case a if isDefinedAt(a) => f(a)
}
}
// now you can write
val f = (i: Int) => i * i
val p = f.asPartial // defined on all integers
val p2 = f.asPartial(_ > 0) // defined only on positive integers
* As discussed in the comments, it may not be entirely clear what "safety" means here. The way I think about it is that a PartialFunction explicitly declares its domain in the following precise sense: if isDefinedAt
returns true for a value x
, then apply(x)
can be evaluated in a way that is consistent with the intent of the function's author. That does not imply that apply(x)
will not throw an exception, but merely that the exception was part of the design of the function (and should be documented).
No, I tried to find one a few months ago and ended up writing my own that's essentially the same as yours.
精彩评论