Piping things in Scala is often very simple - think map for collections, composeand andThen for function composition.
However, I don't seem to find a way to combine the two. I have a function that returns an Option[Double]. I'd like to filter the Double value (reduce its precision) if it's there. andThen is close but needs me to handle the option thingy.
Is there a nice built-in way to deal with this in Scala 2.11?
class Temp( ff: (Object) => Option[Double] )
object Temp {
def apply( f: (Object) => Option[Double] ) = {
def cutTo5Digits(v: Double): Double = {
v - (v % 1e-5)
}
// call 'f', then pipe its output (if some) via 'cutTo5Digits'?
//
//new Temp( f map cutTo5Digits ) // nope
//new Temp( f _ andThen cutTo5Digits _ ) // would need option unwrapping
new Temp((o: Object) => f(o) map ((v: Double) => cutTo5Digits(v))) // compiles
}
}
I think that the best solution would be new Temp(f(_) map cutTo5Digits), what's wrong with it?
But if you want syntax like this: f map cutTo5Digits, then you can use Kleisli from scalaz, where f would be of type Kleisli[Option, Object, Double], i.e:
def apply( f: (Object) => Option[Double] ) = {
def cutTo5Digits(v: Double): Double = v - (v % 1e-5)
val ff = Kleisli(f)
new Temp(ff map cutTo5Digits) // or inline Kleisli(f) map ...
}
Or you can also make cutTo5Digits of type Double => Option[Double], such functions can be chained with Kliesli >=> method and you case can be rewritten as ff >=> cutTo5Digits.
If you want to use the andThen syntax, you can lift your function into a functor, for instance like this:
def liftOption[A, B](f: A => B): Option[A] => Option[B] = _.map(f(_))
To highlight the function composition, you can now write:
(f _) andThen liftOption(cutTo5Digits _)
If you make this conversion implicit, you can even use your original f _ andThen cutTo5Digits _. If you are using Scalaz, you should be able to lift your function via cutTo5Digits.lift[Option].
Related
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.
Given this spinet of code in Scala:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = (d1, d2) => d1 ++ d2
That can be shortened to:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = _ ++ _
What actually the code does is renaming the operator ++ of Map[VertexId, Factor] and therefore: Is there a way to assign that operator to the variable? Like in this imaginary example:
val mapMerge : (Map[VertexId, Factor], Map[VertexId, Factor]) => Map[VertexId, Factor] = Map.++
And probably with type inference it would enough to write
val mapMerge = Map[VertexId,Factor].++
Thanks
Unfortunately, no, because the "operators" in Scala are instance methods — not functions from a typeclass, like in Haskell.
Whey you write _ ++ _, you are creating a new 2-argument function(lambda) with unnamed parameters. This is equivalent to (a, b) => a ++ b, which is in turn equivalent to (a, b) => a.++(b), but not to (a, b) => SomeClass.++(a, b).
You can emulate typeclasses by using implicit arguments (see "typeclasses in scala" presentation)
You can pass "operators" like functions — which are not really operators. And you can have operators which look the same. See this example:
object Main {
trait Concat[A] { def ++ (x: A, y: A): A }
implicit object IntConcat extends Concat[Int] {
override def ++ (x: Int, y: Int): Int = (x.toString + y.toString).toInt
}
implicit class ConcatOperators[A: Concat](x: A) {
def ++ (y: A) = implicitly[Concat[A]].++(x, y)
}
def main(args: Array[String]): Unit = {
val a = 1234
val b = 765
val c = a ++ b // Instance method from ConcatOperators — can be used with infix notation like other built-in "operators"
println(c)
val d = highOrderTest(a, b)(IntConcat.++) // 2-argument method from the typeclass instance
println(d)
// both calls to println print "1234765"
}
def highOrderTest[A](x: A, y: A)(fun: (A, A) => A) = fun(x, y)
}
Here we define Concat typeclass and create an implementation for Int and we use operator-like name for the method in typeclass.
Because you can implement a typeclass for any type, you can use such trick with any type — but that would require writing quite some supporting code, and sometimes it is not worth the result.
Suppose I have a list of functions as so:
val funcList = List(func1: A => T, func2: B => T, func2: C => T)
(where func1, et al. are defined elsewhere)
I want to write a method that will take a value and match it to the right function based on exact type (match a: A with func1: A => T) or throw an exception if there is no matching function.
Is there a simple way to do this?
This is similar to what a PartialFunction does, but I am not able to change the list of functions in funcList to PartialFunctions. I am thinking I have to do some kind of implicit conversion of the functions to a special class that knows the types it can handle and is able to pattern match against it (basically promoting those functions to a specialized PartialFunction). However, I can't figure out how to identify the "domain" of each function.
Thank you.
You cannot identify the domain of each function, because they are erased at runtime. Look up erasure if you want more information, but the short of it is that the information you want does not exist.
There are ways around type erasure, and you'll find plenty discussions on Stack Overflow itself. Some of them come down to storing the type information somewhere as a value, so that you can match on that.
Another possible solution is to simply forsake the use of parameterized types (generics in Java parlance) for your own customized types. That is, doing something like:
abstract class F1 extends (A => T)
object F1 {
def apply(f: A => T): F1 = new F1 {
def apply(n: A): T = f(n)
}
}
And so on. Since F1 doesn't have type parameters, you can match on it, and you can create functions of this type easily. Say both A and T are Int, then you could do this, for example:
F1(_ * 2)
The usual answer to work around type erasure is to use the help of manifests. In your case, you can do the following:
abstract class TypedFunc[-A:Manifest,+R:Manifest] extends (A => R) {
val retType: Manifest[_] = manifest[R]
val argType: Manifest[_] = manifest[A]
}
object TypedFunc {
implicit def apply[A:Manifest, R:Manifest]( f: A => R ): TypedFunc[A, R] = {
f match {
case tf: TypedFunc[A, R] => tf
case _ => new TypedFunc[A, R] { final def apply( arg: A ): R = f( arg ) }
}
}
}
def applyFunc[A, R, T >: A : Manifest]( funcs: Traversable[TypedFunc[A,R]] )( arg: T ): R = {
funcs.find{ f => f.argType <:< manifest[T] } match {
case Some( f ) => f( arg.asInstanceOf[A] )
case _ => sys.error("Could not find function with argument matching type " + manifest[T])
}
}
val func1 = { s: String => s.length }
val func2 = { l: Long => l.toInt }
val func3 = { s: Symbol => s.name.length }
val funcList = List(func1: TypedFunc[String,Int], func2: TypedFunc[Long, Int], func3: TypedFunc[Symbol, Int])
Testing in the REPL:
scala> applyFunc( funcList )( 'hello )
res22: Int = 5
scala> applyFunc( funcList )( "azerty" )
res23: Int = 6
scala> applyFunc( funcList )( 123L )
res24: Int = 123
scala> applyFunc( funcList )( 123 )
java.lang.RuntimeException: Could not find function with argument matching type Int
at scala.sys.package$.error(package.scala:27)
at .applyFunc(<console>:27)
at .<init>(<console>:14)
...
I think you're misunderstanding how a List is typed. List takes a single type parameter, which is the type of all the elements of the list. When you write
val funcList = List(func1: A => T, func2: B => T, func2: C => T)
the compiler will infer a type like funcList : List[A with B with C => T].
This means that each function in funcList takes a parameter that is a member of all of A, B, and C.
Apart from this, you can't (directly) match on function types due to type erasure.
What you could instead do is match on a itself, and call the appropriate function for the type:
a match {
case x : A => func1(x)
case x : B => func2(x)
case x : C => func3(x)
case _ => throw new Exception
}
(Of course, A, B, and C must remain distinct after type-erasure.)
If you need it to be dynamic, you're basically using reflection. Unfortunately Scala's reflection facilities are in flux, with version 2.10 released a few weeks ago, so there's less documentation for the current way of doing it; see How do the new Scala TypeTags improve the (deprecated) Manifests?.
I have a problem that I've been trying to find the best solution to using the existing Scala collections library, but I can't seem to come up with something.
Given a set of functions, I need to find the first function result for some input that satisfies a predicate. Here's a simple implementation:
def findResult[A, B](t: Traversable[Function1[A, B]], value: A, p: B => Boolean): Option[B] = {
var result: Option[B] = None
breakable {
for (e <- t) {
val r = e(value)
if (p(r)) { result = Some(r); break }
}
}
result
}
// test
val f1 = (s: String) => if (s == "a") "aa" else null
val f2 = (s: String) => if (s == "b") "bb" else null
val l = List(f1, f2)
findResult(l, "b", (v: Any) => v != null) must equal(Some("bb"))
Is there a better way to do this using the Collections API?
Edit: One restriction I'd like to put in place is that each function should only be applied once, since while my example is trivial, my actual usage for this is not. This restriction is what led me to the implementation above.
I was going to just comment on tenshi's answer, but then I decided to expand it into an alternate approach. Note that if you use map on a strict Traversable, then the entire list will be mapped before any finding occurs. That means you will end up performing a little extra work.
You could instead just use a find:
def findResult[A, B](t: Traversable[Function1[A, B]], value: A, p: B => Boolean) =
t find (fn => p(fn(value)))
This will instead return the function that satisfies the predicate p for value. If you instead need the result, you need only apply the function to the value again (assuming the function is referentially transparent). This, of course, will therefore perform a little extra work, but is likely to be slightly less extra work than tenshi's technique. Note that the technique you came up with yourself performs no extra work.
[update] If you really don't want to perform any extra work, then you should use a collection view. I had to look this up, but I think I've got a handle on it. Now, stealing tenshi's code outright and adding .view, here's some copypasta from my interactive session:
def f1(x: Int): Int = { println("f1"); x }
f1: (x: Int)Int
def f2(x: Int): Int = { println("f2"); x+1 }
f2: (x: Int)Int
def f3(x: Int): Int = { println("f3"); x+2 }
f3: (x: Int)Int
val fs = List(f1 _, f2 _, f3 _)
fs: List[(Int) => Int] = List(, , )
(fs.view map (f => f(1))) find (_ == 2)
f1
f2
res8: Option[Int] = Some(2)
As you can see, f1 and f2 executed, but not f3. This is because once the result of f2(1) was found to be == 2, the find function was able to stop. That's part of the magic of views: lazy mapping. In fact, the map and find operations are fused together thanks to views! Or so I'm told.
def findResult[A, B](t: Traversable[Function1[A, B]], value: A, p: B => Boolean) =
t.view map (f => f(value)) find p
def even(x: Int) = x % 2 == 0
findResult(fs, 1, even)
f1
f2
res13: Option[Int] = Some(2)
So there you have it. One gem I found in the documentation I linked above was this:
[As of Scala 2.8] All collections except streams and views are strict. The only way to go from a strict to a lazy collection is via the view method. The only way to go back is via force.
You can use view:
def findResult[A, B](t: Traversable[Function1[A, B]], value: A, p: B => Boolean) = {
t.view.map(_(value)).find(p(_))
}
Combination of map and find should work:
def findResult[A, B](t: Traversable[Function1[A, B]], value: A, p: B => Boolean) =
t map (fn => fn(value)) find p
What I'm looking for is this function:
def maybe[A, B](a: Option[A])(f: A => B)(g: () => B): B = a match
{
case Some(x) => f(x)
case None => g()
}
It's in the Haskell prelude so I'm thinking it might be in the Scala standard library somewhere and I've just missed it. I hate having to recode it in projects so I'm wondering if anyone knows where it is, or if it's definitively not there. Or is there a better method for getting this functionality?
Other answers have given the map + getOrElse composition. Just for the record, you can "add" a maybe function to Option in the following way:
implicit def optionWithMaybe[A](opt: Option[A]) = new {
def maybe[B](f: A=>B)(g: =>B) = opt map f getOrElse g
}
It's worth noting that the syntax of higher-order functions in Scala is usually nicer when the function parameter comes last. Thus, a better way to organize maybe would be as follows:
def maybe[B](g: =>B)(f: A=>B) = opt map f getOrElse g
This could be used as follows:
val opt: Option[String] = ...
opt.maybe("") { _.toUpperCase }
You could do
val opt:Option[A] = // ...
val result:B = opt.map(f).getOrElse(g());
getOrElse takes a by-name parameter, so g will only be evaluated if opt is None.
The method would be called fold if it were to adhere to convention (see Either.fold which is the catamorphism for Either).
You can use scalaz, and then you have an implicit conversion to OptionW which has fold, or you can use Scala 2.10.0-M3 and use the builtin Option.fold
scala> Some(1).fold(5)(_ * 2)
res5: Int = 2
scala> (None: Option[Int]).fold(5)(_ * 2)
res7: Int = 5
Note that the scalaz fold signature is fold[X](some: A => X, none: => X), while the builtin seems to be fold[X](none: => X)(some: A => X).
I don't think there is. The best I could come up with is to chain Option's "map" and "getOrElse" together:
scala> var a: Option[String] = Some("hello")
a: Option[String] = Some(hello)
scala> a.map(_.toUpperCase).getOrElse("empty")
res19: java.lang.String = HELLO
scala> a = None
a: Option[String] = None
scala> a.map(_.toUpperCase).getOrElse("empty")
res21: java.lang.String = empty
I don't think there is. However, I'd write it to take g by name:
def maybe[A, B](a: Option[A])(f: A => B)(g: => B): B = a.map(f).getOrElse(g)
This is more Scala- and Haskell-like and a bit nicer to use.
I'd use Option.fold for this:
opt.fold(g)(f)
Note that g is by-name, just like getOrElse. Also note the inversion of the cases.