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?
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.
Related
I am Scala beginner.I know the syntax for function declaration
def function_name(parameter:return_type):return_type = {function_body}
Refering this link https://livebook.manning.com/#!/book/scala-in-action/chapter-2/161.
I can't get over the code written there
def breakable(op: => Unit) { ... }
Can anyone explain this?
This is a shorthand syntax for declaring a function that returns Unit (roughly the same as void in C-like languages).
The definition
def breakable(op: => Unit) { ... }
is the same as
def breakable(op: => Unit): Unit = { ... }
This syntax may be removed in later versions of Scala, so best to include the = even when declaring a function that returns Unit.
The parameter is declared as op: => Unit which means it is a call-by-name parameter. This means that the expression that is passed to this parameter is only evaluated when it is used, and is evaluated every time it is used. In this case it means that you can pass a block of code to breakable in a convenient way:
breakable {
println("I have been called")
}
Each time breakable evaluates op, the println statement will be executed.
In scala function can take values(pre-computed values or not-yet-computed values) along with function as arguments.
So, function which takes computed values as argument,
scala> def f(a: Int) = a * 100
f: (a: Int)Int
Example of function which takes a block of code returning Int (not yet computed) , block of code here could be just anonymous or existing method(not a function; that's where things get messy)
scala> def f(a: => Int) = a
f: (a: => Int)Int
and to use it,
scala> def a: Int = 100 * 100
a: Int
scala> f(a) //a returns Int so confirms a: => Int
res3: Int = 10000
In your example, def breakable(op: => Unit) { ... } takes a argument which WILLL be computed as Unit.
For example, you can pass println, which returns Unit,
scala> def breakable(op: => Unit) = op
breakable: (op: => Unit)Unit
scala> breakable { println("i m learning fp") }
i m learning fp
The other thing you will see is function taking function as argument, as in Functor, Monad etc.
For example, map/ flatMap on List[Int] would be
final override def map[B](f: A => B): List[B]
final override def flatMap[B](f: Int => scala.collection.IterableOnce[B]): List[B]
Update (2018): my prayers were answered in Dotty (Type Lambdas), so the following Q&A is more "Scala 2.x"-related
Just a simple example from Scala:
scala> def f(x: Int) = x
f: (x: Int)Int
scala> (f _)(5)
res0: Int = 5
Let's make it generic:
scala> def f[T](x: T) = x
f: [T](x: T)T
scala> (f _)(5)
<console>:9: error: type mismatch;
found : Int(5)
required: Nothing
(f _)(5)
^
Let's look at eta-expansion of polymorphic method in Scala:
scala> f _
res2: Nothing => Nothing = <function1>
Comparison with Haskell:
Prelude> let f x = x
Prelude> f 5
5
Prelude> f "a"
"a"
Prelude> :t f
f :: t -> t
Haskell did infer correct type [T] => [T] here.
More realistic example?
scala> identity _
res2: Nothing => Nothing = <function1>
Even more realistic:
scala> def f[T](l: List[T]) = l.head
f: [T](l: List[T])T
scala> f _
res3: List[Nothing] => Nothing = <function1>
You can't make alias for identity - have to write your own function. Things like [T,U](t: T, u: U) => t -> u (make tuple) are impossible to use as values. More general - if you want to pass some lambda that rely on generic type (e.g. uses generic function, for example: creates lists, tuples, modify them in some way) - you can't do that.
So, how to solve that problem? Any workaround, solution or reasoning?
P.S. I've used term polymorphic lambda (instead of function) as function is just named lambda
Only methods can be generic on the JVM/Scala, not values. You can make an anonymous instance that implements some interface (and duplicate it for every type-arity you want to work with):
trait ~>[A[_], B[_]] { //exists in scalaz
def apply[T](a: A[T]): B[T]
}
val f = new (List ~> Id) {
def apply[T](a: List[T]) = a.head
}
Or use shapeless' Poly, which supports more complicated type-cases. But yeah, it's a limitation and it requires working around.
P∀scal is a compiler plugin that provides more concise syntax for encoding polymorphic values as objects with a generic method.
The identity function, as a value, has type ∀A. A => A. To translate that into Scala, assume a trait
trait ForAll[F[_]] {
def apply[A]: F[A]
}
Then the identity function has type ForAll[λ[A => A => A]], where I use the kind-projector syntax, or, without kind-projector:
type IdFun[A] = A => A
type PolyId = ForAll[IdFun]
And now comes the P∀scal syntactic sugar:
val id = Λ[Α](a => a) : PolyId
or equivalently
val id = ν[PolyId](a => a)
("ν" is the Greek lowercase letter "Nu", read "new")
These are really just shorthands for
new PolyId {
def apply[A] = a => a
}
Multiple type parameters and parameters of arbitrary kinds are supported by P∀scal, but you need a dedicated variation on the above ForAll trait for each variant.
I really like #Travis Brown 's solution:
import shapeless._
scala> Poly(identity _)
res2: shapeless.PolyDefns.~>[shapeless.Id,shapeless.Id] = fresh$macro$1$2$#797aa352
-
scala> def f[T](x: T) = x
f: [T](x: T)T
scala> Poly(f _)
res3: shapeless.PolyDefns.~>[shapeless.Id,shapeless.Id] = fresh$macro$2$2$#664ea816
-
scala> def f[T](l: List[T]) = l.head
f: [T](l: List[T])T
scala> val ff = Poly(f _)
ff: shapeless.PolyDefns.~>[List,shapeless.Id] = fresh$macro$3$2$#51254c50
scala> ff(List(1,2,3))
res5: shapeless.Id[Int] = 1
scala> ff(List("1","2","3"))
res6: shapeless.Id[String] = 1
Poly constructor (in some cases) will give you eta-expansion into Shapeless2 Poly1 function, which is (more-less) truly generic. However it doesn't work for multi-parameters (even with multi type-parameters), so have to "implement" Poly2 with implicit + at approach (as #som-snytt suggested), something like:
object myF extends Poly2 {
implicit def caseA[T, U] = at[T, U]{ (a, b) => a -> b}
}
scala> myF(1,2)
res15: (Int, Int) = (1,2)
scala> myF("a",2)
res16: (String, Int) = (a,2)
P.S. I would really want to see it as a part of language.
It seems to do this you will need to do a bit type hinting to help the Scala type inference system.
def id[T] : T => T = identity _
So I guess if you try to pass identity as a parameter to a function call and the types of that parameter are generic then there should be no problem.
Given two functions:
def f(a: String, b: Int): Int = a.length + b
val g: Int => String = _.toString
why is it that I can compose a partially applied f with g by means of an intermediate assignment:
val f_ = f(_: String, 42)
f_ andThen g
// String => String = <function1>
but not directly:
f(_: String, 42) andThen g
// error: value andThen is not a member of Int
Is this a problem with the type inferencer or somehow expected behavior?
This is just a syntactic error, if you turn on -Xprint:parser option you'll see the difference between your expression and the correct one, i.e: (f(_: String, 42)) andThen g.
Your expression:
((x$1: String) => f((x$1: String), 42).andThen(g))
The correct one:
((x$1: String) => f((x$1: String), 42)).andThen(g)
You can see the difference. It happens because of expansion rule, scalac first normalise syntax to the dot form and then expand it. The same rule applies to this form of function application: func(_) which is expanded to the inner-most braces, I don't remeber where in SLS it's written.
I want to programmatically compose several functions. If these functions are all of the same type, I can do the following:
def a(x: Int): Int = x+1
def b(y: Int): Int = y/2
def c(z: Int): Int = z*4
val f1 = (a _) andThen (b _) andThen (c _)
val f2 = List((a _), (b _), (c _)).reduce(_ andThen _)
At which point f1 and f2 are the same thing, and this compiles because the List that defines f2 is a List[Function1[Int,Int]]
However, if I want to chain together multiple compatible functions with different types using the same basic reduce technique, I get an error.
def d(x: Double): Int = x.toInt
def e(y: Int): String = y.toString
def f(z: String): Double = z.toDouble*4
//Works fine
val f3 = (d _) andThen (e _) andThen (f _)
//Doesn't compile
val f4 = List((d _), (e _), (f _)).reduce(_ andThen _)
The second option doesn't compile because the list that defines f4 is inferred as a List[Function1[Any,Any]], but I can't figure out if theres a clean type-safe way to take an ordered collection of functions of the form Function1[A,B],Function1[B,C],Function1[C,D],...,Function1[X,Y] and glue them together as a Function1[A,Y] like this.
Any ideas?
There are two problems here. The first (as you've noted) is that the list has a single element type, which will be inferred to be the least upper bound of the types of the elements it contains, which in this case is the extremely boring and useless String with Int with Double => Any. Heterogeneous lists provide one way of addressing this part of the problem, as I'll show in a second.
The second problem is that the _ andThen _ is insufficiently polymorphic (as Bob Dalgleish points out in a comment above). The argument to reduce will be a function with a concrete input type and a concrete output type, so even if we had a heterogeneous list, there's no way we could reduce it with a Function from the Scala standard library—we'd need a polymorphic function value instead.
Fortunately (if you really want to do this kind of thing in Scala), there's a great library called Shapeless that provides nice implementations of both heterogeneous lists and polymorphic functions. For example, you could write the following:
def d(x: Double): Int = x.toInt
def e(y: Int): String = y.toString
def f(z: String): Double = z.toDouble * 4
import shapeless._
object andThen extends Poly2 {
implicit def functions[A, B, C] = at[A => B, B => C](_ andThen _)
}
And then:
scala> val andThenned = HList((d _), (e _), (f _)).reduceLeft(andThen)
andThenned: Double => Double = <function1>
scala> andThenned(13.0)
res0: Double = 52.0
I think this is pretty neat.
Let's define f, a function that supports currying :
def f(a: Int)(b: Int) = a + b
This code doesn't compile
def g= f(1)
<console>:10: error: missing arguments for method f;
follow this method with `_' if you want to treat it as a partially applied function
def g= f(1)
I've found these 2 workarounds :
scala> def h = f(1) _
h: Int => Int
scala> def i : Int => Int = f(1)
i: Int => Int
But i don't understand why the inference engine need help in a trivial case like that ?
This is because def f(a: Int)(b: Int) is not a function but a method with multiple parameter lists. Scala doesn't unify both of them to a single concept, thus you have to distinguish between them as well.
To partially apply a method with multiple parameter lists (and therefore implicitly convert this method to a function) you have to add an underscore after the method, as the error message suggests. When you tell the compiler explicitly which signature you want to have, it can also implicitly convert a method to a function (as seen in your second workaround).
If you want to use currying in Scala it's best to create a function from the beginning:
scala> val f = (a: Int) => (b: Int) => a+b
f: Int => (Int => Int) = <function1>
scala> val g = f(1)
g: Int => Int = <function1>