val even: PartialFunction[Int, String] = PartialFunction[Int, String] {
case i if i % 2 == 0 => i + " is even"
}
val isEven: PartialFunction[Int, String] = {
case i if i % 2 == 0 => i + " is even"
}
val odd: PartialFunction[Int, String] = PartialFunction[Int, String] {
case x if x % 2 == 1 => x + " is odd"
}
val isOdd: PartialFunction[Int, String] = {
case x if x % 2 == 1 => x + " is odd"
}
val tot = even orElse odd
val tot2 = isEven orElse isOdd
println(tot(3))
println(tot2(3))
In this code tot function throws match error while tot2 function works as expected. Only difference between them is the way they're defined. Can anyone explain why such difference in result?
Thanks in advance!!!
At the core the difference is that isDefinedAt on the partial function is not being defined as you would expect on the version using the PartialFunction.apply method. That is actually why this method is now deprecated, PartialFunction.apply is meant to convert a total function into a partial function with isDefinedAt always returning true, which means it will think it is defined for 3 in your example, and try to apply the function instead of falling back to the even function you have supplied as an alternative.
This brings up a common sore point in the community regarding total functions vs partial functions. PartialFunction is a subtype of Function, I guess in the OO design sense that it is a function with an additional method (isDefinedAt) which tells you whether the function is defined for a particular value. Many feel this is a mistake, as in the Liskov sense, Function should be a subtype of PartialFunction because you can use a Function anywhere a PartialFunction is expected, but if you use a PartialFunction where a Function is expected it will compile, then may fail at runtime. My feeling is that it is because Function can be considered to have an implicit isDefinedAt that always returns true, which would allow you to correct the relationship and make Function a subtype of PartialFunction. This comes to a head in PartialFunction.apply which expects a total function and due to this expectation defines isDefinedAt to always return true, but it can’t enforce that expectation, so if you call PartialFunction.apply(somePartialFunction) bad things happen that most programmers won’t expect.
PartialFunction.apply Scaladoc
PartialFunction[Int, String]{...} is syntactic sugar for
PartialFunction[Int, String].apply({...})
To minimize:
val even: PartialFunction[Int, String] = PartialFunction[Int, String]{
case i if i % 2 == 0 => i + " is even"
}
val isEven: PartialFunction[Int, String] = {
case i if i % 2 == 0 => i + " is even"
}
println(even.isDefinedAt(3)) //true
println(isEven.isDefinedAt(3)) //false
In the first two cases you are calling the apply function in the companion object of PartialFunction. I know, that sounds as if it should
work. But it doesn't because PartialFunction.apply should read PartialFunction.fromTotalFunction.
This is a scala language issue and, if I remember correctly (can't find the ticket at the moment, will look later), this apply function will be gone and replaced by fromTotalFunction in Scala 2.13.
UPDATE
The ticket I meant was #6005
It seems that PartialFunction.apply is already deprecated since Scala 2.12.5.
Related
Since PartialFunction.apply is deprecated since Scala 2.12.5, how can I create a PartialFunction without declaring a new variable?E.g. I was able to do:
List(0).map(PartialFunction[Int,Int]{
case 0 => 100
case x => x*100
}.orElse{
case 100 => 0
})
How to write the same thing in Scala 2.12.5 in one statement?
The deprecation warning actually tells you what to do: "use an explicit type annotation instead":
val f = ({ case 0 => 100; case x => x * 100 }: PartialFunction[Int, Int])
.orElse[Int, Int]{ case 100 => 0 }
Update
Why the apply was deprecated (probably):
val pf = PartialFunction[Int, Int]{ case 100 => 42 }
pf.isDefinedAt(50)
// res2: Boolean = true
The problem is: it's a partial function that is implicitly cast into normal function, and then again wrapped into partial function. It completely loses all the information about where it is actually defined, so isDefinedAt returns true for all inputs.
I'm a little baffled by the error
[error] found : A => B
[error] required: PartialFunction[A,B]
I can fix it by wrapping the function I'm using in Function.unlift(x => Some(...)) but this seems like something I would have expected to be implicit given the doc's definition of "A partial function of type PartialFunction[A, B] is a unary function where the domain does not necessarily include all values of type A".
With the word "necessarily", this definition seems to explicitly include a function A => B being a PartialFunction[A, B]. Am I mis-reading this, or missing something else?
To add to my confusion, while I get this error in my code with Throwable and com.twitter.util.Future[com.twitter.finagle.http.Response], I cannot reproduce it with a simpler example.
PartialFunction does not necessarily include all values of type A this means you can only handle the target value without the other values. like the pattern match.
Example 1:
List(1, 2, 3, 4, 5).collect({
case x if x % 2 == 0 => x + 1
})
In the above code snippet, we only want to handle the even numbers and plus 1. if there is no PartialFunction, we will need to filter even numbers firstly and map again.
Example 2:
List(1, 2, "one", "two").collect({
case x: String => x + 1
})
In the Example 2, we only want to handle the String type values in the list, so PartialFunction also can used to match the type.
So if you want to implicit to convert Function to PartialFunction, I think you can define implicit method like:
implicit def convertFunctionToPartialFunction[A, B](f: A => Option[B]) = {
Function.unlift(f)
}
val a: Int => Option[Int] = (x: Int) => {
if (x % 2 == 0) {
Some(x + 1)
} else None
}
val res = List(1, 2, 3, 4, 5).collect(a)
but seems a Function is ugly...
PartialFunction[A, B] is a subtype of A => B. In particular, it has the method isDefinedAt which A => B doesn't have. So where a PartialFunction is expected, a normal function can't be used.
Your "simpler example" does the opposite: it passes a PartialFunction to something that expects a function. This direction works fine.
Instead of messing around with Function.unlift, you can just use
{ case x => f(x) }
(since PartialFunction is the expected type in your case). There's also PartialFunction(f), but it's deprecated since 2.12.5.
I run into a case that monad on return type hinders the high-order function programming.
val fOpt: (x: Int) => Option[Int]
def g(f: Int=>Int): Int
How do I call g(fOpt) and get result as Option[Int] ?
My solution is Try(g(fOpt(_).get)).toOption. but I'm not satisfied.
Is there methods that I don't know can solve this. I ask this because I know less about functional programming (so many pattern and theory).
I expect there would be something like functor for function return such that it can work like val ret:Option[Int] = fOpt.mapReturn(f=>g(f))
You can easily implement the syntax that you proposed (I called it toAmbient instead of mapReturn, and later I replaced f by h to make the separation of the identifiers more obivous).
Here is an implementation that uses an implicit wrapper class on functions:
implicit class UnsafeEmbedAmbientOps[X, Y](f: X => Option[Y]) {
class NoneToAmbientEmbeddingException extends RuntimeException
def toAmbient[Z](a: (X => Y) => Z): Option[Z] = {
try {
Some(a(f(_).getOrElse(throw new NoneToAmbientEmbeddingException)))
} catch {
case e: NoneToAmbientEmbeddingException => None
}
}
}
Now you can define f: Int => Option[Int] and various g, g2 that take Int => Int and return Int:
val f: Int => Option[Int] = x => Map(1 -> 1, 2 -> 4, 3 -> 9).get(x)
def g(f: Int => Int): Int = f(1) + f(2)
def g2(f: Int => Int): Int = f(1) + f(42)
and then pass f to g and g2 as follows:
println(f.toAmbient(h => g(h)))
println(f.toAmbient(h => g2(h)))
This will print:
Some(5)
None
Extended comment
I want to try to explain why I find Try(g(fOpt(_).get)).toOption actually good.
Suppose that there were some natural way to transform every
f: X => Option[Y]
into an
fPrime: X => Y
This would imply that there is a natural way to transform every Unit => Option[Y] into an Unit => Y. Since Unit => Y is essentially the same as Y, this would in turn imply that there is some way to transform every Option[Y] into an Y. But there is no natural transformation from Option[Y] to Y. This is a rather general phenomenon: while there is point/unit, and it is always easy to get into the monad from X to M[X], there is generally no safe/easy/lossless way to get out of a monad from M[X] to X, e.g.:
Calling get on Option[X] returns X, but can throw NoSuchElementException
Likewise, calling head on List can throw exceptions, and also throws away the tail.
Awaiting a Future is blocking
Sampling an X from a random Distribution[X] leaves you with a fixed X, but erases information about probabilities of all the other possible X
etc.
The fact that you can work around the type signature g(f: Int => Int) with Try is because the Int => Int part is not really precise: it is not the identity monad, but rather the default ambient monad that supports state and exceptions. In "reality", g is rather something like g(f: Int => DefaultAmbientMonad[Int]), because f can also throw exceptions.
Now, the interesting thing is that while there is no guaranteed way to get from Option[X] to X, there actually is a way to get from Option[X] to DefaultAmbientMonad[X]: just throw some very special NoneEmbeddingException if the Option is None. Getting from DefaultAmbientMonad to Option is again unsafe: you can catch your special NoneEmbeddingException, but then you have to "pray" that no other exceptions will be thrown (that's why it is "unsafe").
So, the most "systematic" way to pass fOpt to g would actually be
class NoneEmbeddingException extends RuntimeException
try {
Option(g(fOpt(_).getOrElse(throw new NoneEmbeddingException)))
} catch {
case e: NoneEmbeddingException => None
}
This is what I've implemented in the code snippet above.
But this is almost what you have already with Try(...).toOption, except that you use the predefined NoSuchElementException instead of the somewhat contrived NoneEmbeddingException!
So, I would just say: your solution is correct, it can be justified by a systematic discussion of the natural transformations from the Option monad to the default ambient monad, and it is not particularly astonishing. My personal opinion: just use Try(...).toOption, it's ok.
I came across a code similar to this, and it was surprised that it even compiles:
scala> val halfSize: PartialFunction[String, Int] = _.length match {
case even if even % 2 == 0 => even / 2
}
halfSize: PartialFunction[String,Int] = <function1>
scala> List("x", "xx").collect(halfSize)
res1: List[Int] = List(1)
As far as I known, the valid syntax to define a PartialFunction is a case function:
val halfSize: PartialFunction[String, Int] = {
case s if s.length % 2 == 0 => s.length / 2
}
The first code seems more optimized since it calls length only once. But even in the SLS I was not able to find the explanation of the syntax. Is this an undocumented feature of scalac ?
The rules are given in https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#anonymous-functions:
The eventual run-time value of an anonymous function is determined by the expected type:
...
PartialFunction[T, U], if the function literal is of the shape x => x match { … }
In this case the literal does have such a shape, as rogue-one's answer explains, so PartialFunction is allowed as the expected type.
(EDIT: actually, it doesn't, since it matches x.length instead of x. This looks like a minor bug, but one which should be fixed by changing the specification.)
A PartialFunction's value receives an additional isDefinedAt member, which is derived from the pattern match in the function literal, with each case's body being replaced by true, and an added default (if none was given) that evaluates to false.
So in this case it ends up with
def isDefinedAt(x: String) = x.length match {
case even if even % 2 == 0 => true
case _ => false
}
val halfSize: PartialFunction[String, Int] = _.length match {
case even if even % 2 == 0 => even / 2
}
The underscore (_) in the above function is just a short hand notation that refers to the single argument of the function. Thus the above snippet is just a short form of
val halfSize: PartialFunction[String, Int] = { (x: String) => x.length match {
case even if even % 2 == 0 => even / 2
}
}
I have a function in a context, (in a Maybe / Option) and I want to pass it a value and get back the return value, directly out of the context.
Let's take an example in Scala :
scala> Some((x:Int) => x * x)
res0: Some[Int => Int] = Some(<function1>)
Of course, I can do
res0.map(_(5))
to execute the function, but the result is wrapped in the context.
Ok, I could do :
res0.map(_(5)).getOrElse(...)
but I'm copy/pasting this everywhere in my code (I have a lot of functions wrapped in Option, or worst, in Either...).
I need a better form, something like :
res0.applyOrElse(5, ...)
Does this concept of 'applying a function in a concept to a value and immediatly returning the result out of the context' exists in FP with a specific name (I'm lost in all those Functor, Monad and Applicatives...) ?
You can use andThen to move the default from the place where you call the function to the place where you define it:
val foo: String => Option[Int] = s => Some(s.size)
val bar: String => Int = foo.andThen(_.getOrElse(100))
This only works for Function1, but if you want a more generic version, Scalaz provides functor instances for FunctionN:
import scalaz._, Scalaz._
val foo: (String, Int) => Option[Int] = (s, i) => Some(s.size + i)
val bar: (String, Int) => Int = foo.map(_.getOrElse(100))
This also works for Function1—just replace andThen above with map.
More generally, as I mention above, this looks a little like unliftId on Kleisli, which takes a wrapped function A => F[B] and collapses the F using a comonad instance for F. If you wanted something that worked generically for Option, Either[E, ?], etc., you could write something similar that would take a Optional instance for F and a default value.
You could write something like applyOrElse using Option.fold.
fold[B](ifEmpty: ⇒ B)(f: (A) ⇒ B): B
val squared = Some((x:Int) => x * x)
squared.fold {
// or else = ifEmpty
math.pow(5, 2).toInt
}{
// execute function
_(5)
}
Using Travis Browns recent answer on another question, I was able to puzzle together the following applyOrElse function. It depends on Shapeless and you need to pass the arguments as an HList so it might not be exactly what you want.
def applyOrElse[F, I <: HList, O](
optionFun: Option[F],
input: I,
orElse: => O
)(implicit
ftp: FnToProduct.Aux[F, I => O]
): O = optionFun.fold(orElse)(f => ftp(f)(input))
Which can be used as :
val squared = Some((x:Int) => x * x)
applyOrElse(squared, 2 :: HNil, 10)
// res0: Int = 4
applyOrElse(None, 2 :: HNil, 10)
// res1: Int = 10
val concat = Some((a: String, b: String) => s"$a $b")
applyOrElse(concat, "hello" :: "world" :: HNil, "not" + "executed")
// res2: String = hello world
The getOrElse is most logical way to do it. In regards to copy/pasting it all over the place - you might not be dividing your logic up on the best way. Generally, you want to defer resolving your Options (or Futures/etc) in your code until the point you need to have it unwrapped. In this case, it seems more sensible that your function takes in an an Int and returns an Int, and you map your option where you need the result of that function.