Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nice syntax for function composition in Scala

Tags:

scala

I would like to arrive to a syntax as productive as Haskell's desort = (reverse . sort) in Scala... Here is my attempt:

implicit class Composition[A,B,C](val g: A => B) {
  def o(f: B => C): A => C = { a:A => f(g(a))}
}

val fg = cos _ o sin

Is there any way we can get rid of the _in the declaration of gf?

like image 213
Frank Avatar asked Dec 29 '16 01:12

Frank


1 Answers

For functions yes, but for methods, no. Your problem is that you're trying to use a method for g, and not a function. For functions, there is already a method for this called andThen:

val f: Int => Int = _ + 1
val g: Int => String = _.toString

scala> val fg = f andThen g
fg: Int => String = <function1>

scala> fg(2)
res3: String = 3

Your own implicit class will work as well (though I haven't looked at the exact semantics you desire), using functions like f and g, as I've defined them. It will even work for a function and a method (in that order).

def a(i: Int): Int = i + 1
def b(i: Int): String = i.toString

scala> f andThen a
res4: Int => Int = <function1>

However, a andThen b does not work as-is, because a is a method, which you cannot call andThen on. In order to use andThen, a needs to be converted to a function, which will not happen automatically, because a function isn't necessarily expected. a _ andThen b eta-expands a into a function, in which has a method called andThen, and can be provided an argument of b (a method), because the compiler will implicitly convert b to a function, since a function is the only thing that is expected as an argument of andThen. Function isn't the only type with a method called andThen, so the compiler can't expect one 100% of the time to make the conversion from method to function for a.

like image 70
Michael Zajac Avatar answered Sep 20 '22 04:09

Michael Zajac