Use of compose function - scala

This code :
def compose[A, B, C](f: B => C, g: A => B): A => C =
a => f(g(a)) //> compose: [A, B, C](f: B => C, g: A => B)A => C
def f(a : Int) = a + 1 //> f: (a: Int)Int
def g(a : Int) = a + 1 //> g: (a: Int)Int
compose[Int,Int,Int](f(1) , g(1))
causes compiler error :
Multiple markers at this line - type mismatch; found : Int required: Int => Int - type mismatch; found : Int
required: Int => Int
But since f and g are functions which take an Int and return an Int, does this not match function definition of f: B => C as B & C will be typed to an Int ?

You should compose functions (you're composing Ints).
As a result you get another function which is the composition.
Then you can pass the parameter to the composed function.
compose[Int,Int,Int](f , g)(1)
BTW, there's a compose (and andThen) method in Scala
(f _).compose(g)(1)
https://twitter.github.io/scala_school/pattern-matching-and-functional-composition.html

Related

Resolution of abstract types in scala functions

I am new to Scala and trying to explore the syntax of the language, but I ran into an issue about abstract types.
def func5(x : Int, y : Int): Int = x * y
def func55(x : Double, y : Double): Double = x / y
def func6[A,B](f : (A,A) => A, g: (B,B) => B) :
(Int,Int,Double,Double) => Double = (x,y,a,z) => {f(x,y)+g(a,z)}
func6(func5, func55)(3,4,7.0d,4.2d)
Here it gives me:
+g(a,z)} expected string but given B
Can someone enlight me about that ?
Thanks for your time.
The problem is that func6 is trying to add a value of type A to a value of type B. Or more specifically, it is trying to call a method + on an object of type A with an argument of type B. Both A and B could be any type, and there isn't really a generic way to "add" two objects together.
So you might expect this to fail because there is no + operator on A. But Scala (for some reason) does have a generic definition of + for all objects. This generic + takes an argument of type String but func6 is giving it type B, which is why you get the error
found: B, required: String
Functions f and g are generic functions, which do not take ints or doubles as arguments (only A and B).
def func6[A,B](f : (A,A) => A, g: (B,B) => B) :
(A,A,B,B) => (A, B) = (x,y,a,z) => {
(f(x,y),g(a,z))
}
Something like that will work. But you can not use '+' at the end of the function, because it is not defined for types A and B.
You could also define implicit plus operator for A and B.
def func5(x : Int, y : Int): Int = x * y
def func55(x : Double, y : Double): Double = x / y
def func6[A,B](f : (A,A) => A, g: (B,B) => B)(implicit plusOperation: PlusOperation[A, B]) :
(A,A,B,B) => B = (x,y,a,z) => {
plusOperation.add(f(x,y),g(a,z))
}
trait PlusOperation[A, B] {
def add(a: A, b: B): B
}
class IntToDoublePlus extends PlusOperation[Int, Double] {
override def add(a: Int, b: Double): Double = a + b
}
implicit val plusOp: PlusOperation[Int, Double] = _ + _
func6(func5, func55).apply(3,4,7.0d,4.2d)

Type mismatch for function composition

I have defined an identity function and a composition function:
def identity[T](x: T): T = x
def composition[A, B, C](f: A => B, g: B => C)(x: A) = g(f(x))
I am trying to assert that the identity function can be applied on both sides with the same result:
assert(composition((x: Int) => x + 1, identity)(3) == composition(identity, (x: Int) => x + 1)(3))
However, I am getting these errors:
Error:(7, 40) type mismatch;
found : Nothing => Nothing
required: Int => Nothing
assert(composition((x: Int) => x + 1, identity)(3) == composition(identity, (x: Int) => x + 1)(3));}
And:
Error:(7, 68) type mismatch;
found : Nothing => Nothing
required: A => Nothing
assert(composition((x: Int) => x + 1, identity)(3) == composition(identity, (x: Int) => x + 1)(3));}
Why is this the case?
This is the case because the compiler is having difficulty inferring the types properly, specifically inferring what A is. You can help him by placing A as the first argument and each function in a separate parameter list:
def composition[A, B, C](x: A)(f: A => B)(g: B => C) = g(f(x))
And now this works as expected:
scala> :pa
// Entering paste mode (ctrl-D to finish)
def identity[T](x: T): T = x
def composition[A, B, C](x: A)(f: A => B)(g: B => C) = g(f(x))
// Exiting paste mode, now interpreting.
identity: [T](x: T)T
composition: [A, B, C](x: A)(f: A => B)(g: B => C)C
scala> println(composition(3)((x: Int) => x + 1)(identity) == composition(3)(identity)((x: Int) => x + 1))
true
Alternatively, you can specify the type parameter explicitly to help the compiler infer the right type:
println(composition((x: Int) => x + 1, identity[Int], 3) ==
composition(identity[Int], (x: Int) => x + 1, 3))
Below should work. Note the type param for the identity function.
assert(composition((x: Int) => x + 1, identity[Int])(3) == composition(identity[Int], (x: Int) => x + 1)(3))
Since you have not specified the type param for the identity function, it becomes Nothing and it does not match with the type signature of your method.

How to execute user-defined function that accepts and returns another?

Here's my function:
def partial1[A, B, C](a: A, f: (A, B) => C): B => C = (b: B) => f(a, b)
> partial1: [A, B, C](a: A, f: (A, B) => C)B => C
Here I invoke the function partial1:
def fun(a: Int, b: Int) = a + b
> fun: (a: Int, b: Int)Int
val r = partial1(1, fun)
> r : Int => Int = <function1>
r(fun(1,3))
> res0: Int = 5
So r is a function which takes a function as parameter and returns a Function1 (a function with 1 parameter). Should Int => Int not be Int, Int since two Ints are the function parameters?
Why can't I implement Partial1 like partial1(1,(fun(1,3))) which causes compiler error : type mismatch; found : Int required: (?, ?) => ? ?
First of all, partial1 isn't a partial function. It's a function that returns another function so it's a higher-order function.
The compile error you're getting is because partial1 expects a function (A, B) => C, but you're passing fun(1,3), which evaluates to an Int. And Int is not the same as (Int, Int) => Int.
class ex03 {
def partial1[A,B,C](a:A, f:(A,B) => C): B => C = f(a,_)
}
class ex03Test extends UnitSpec {
behavior of "partial1"
it should "return 6" in {
val e = new ex03
val multiplyByTwo = e.partial1(2, (a:Int, b:Int) => a * b)
multiplyByTwo(3) mustBe 6
}}

How to set type parameter bound in scala to make generic function for numerics?

I want to make a sum function that works with all Numeric types.
This works:
object session {
def mapReduce[A](f: A => A, combine: (A, A) => A, zero: A, inc: A)
(a: A,b: A)
(implicit num:Numeric[A]): A = {
def loop(acc: A, a: A) =
if (num.gt(a, b)) acc
else combine(f(a), mapReduce(f, combine, zero, inc)(num.plus(a, inc), b))
loop(zero, a)
}
def sum(f: Int => Int)
(a: Int, b: Int) : Int = {
mapReduce(f, (x: Int, y: Int) => x + y, 0, 1)(a, b)}
sum(x => x)(3, 4) //> res0: Int = 7
def product(f: Int => Int)
(a: Int, b: Int): Int = {
mapReduce(f, (x: Int, y: Int) => x * y, 1, 1)(a, b)}
product(x => x)(3, 4) //> res1: Int = 12
def fact(n: Int) = product(x => x)(1, n)
fact(5) //> res3: Int = 120
}
but when I try to make sum generic like this:
def sum[A](f: A => A)
(a: A, b: A)
(implicit num:Numeric[A]): A = {
mapReduce(f, (x: A, y: A) => num.plus(x, y), 0, 1)(a, b)}
sum(x => x)(3.0, 4.0) // should be 12.0
I get this error on f
type mismatch; found : A => A required: Any => Any
when i pass it to mapReduce. So what do i need to do to make sum accept any Numeric value?
If I'm not mistaken, the other answer is almost correct except for the fact that the type has to be made explicit when calling mapReduce instead of when calling sum.
So in your generic definition of sum, you might want to do this:
def sum[A](f: A => A)(a: A, b: A)(implicit num: Numeric[A]): A =
mapReduce[A](f, num.plus, num.zero, num.one)(a, b)
That's however not enough for the typer to infer the concrete type of A, e.g. Double when calling sum(x => x)(3.0, 4.0). The reason for this is that the typer is going from first to last parameter list, left to right.
Your first parameter list declares f: A => A and only the second parameter list defines (a: A, b: A). Once the typer reaches the end of the first parameter list, it doesn't know what A exactly is, and hence it fixes the type of A to some "abstract" A. The only thing that it knows about A at this point is that it is a subtype of Any.
When the typer then gets to the second parameter list, it could theoretically infer A as Double or whatever your concrete type is, but as said before the type has already been fixed. This is just a flaw of Scala's typer which can easily be circumvented once you get the hang of it.
More precisely, all you have to do is help the typer by switching the first and second parameter lists like so:
def sum[A](a: A, b: A)(f: A => A)(implicit num: Numeric[A]): A =
mapReduce[A](f, num.plus, num.zero, num.one)(a, b)
Then it's possible to call sum without being explicit about the type, e.g.
Console println sum(3.0, 4.0)(x => x) // 7.0
Give the type of sum explicitly. I have already provided an answer to a similar question in
A simple foldRight type issue in Scala.
Questions are totally different but the reason is exactly the same.

How does a "case" anonymous function really work in Scala?

Dеar Scala,
scala> val f1: ((Int, Int)) => Int = { case (a, b) => a + b }
f1: ((Int, Int)) => Int = <function1>
scala> val f2: (Int, Int) => Int = { case (a, b) => a + b }
f2: (Int, Int) => Int = <function2>
huh?!
scala> f1(1, 2)
res2: Int = 3
Ok...
scala> def takesIntInt2Int(fun: (Int, Int) => Int) = fun(100, 200)
takesIntInt2Int: (fun: (Int, Int) => Int)Int
scala> def takesTuple2Int(fun: ((Int, Int)) => Int) = fun(100, 200)
takesTuple2Int: (fun: ((Int, Int)) => Int)Int
scala> takesIntInt2Int(f2)
res4: Int = 300
scala> takesIntInt2Int(f1)
<console>:10: error: type mismatch;
found : ((Int, Int)) => Int
required: (Int, Int) => Int
takesIntInt2Int(f1)
^
scala> takesTuple2Int(f1)
res6: Int = 300
scala> takesTuple2Int(f2)
<console>:10: error: type mismatch;
found : (Int, Int) => Int
required: ((Int, Int)) => Int
takesTuple2Int(f2)
Right. And now, look at this!
scala> takesTuple2Int { case (a, b, c) => a + b + c }
<console>:9: error: constructor cannot be instantiated to expected type;
found : (T1, T2, T3)
required: (Int, Int)
takesTuple2Int { case (a, b, c) => a + b + c }
^
scala> takesIntInt2Int { case (a, b, c) => a + b + c }
<console>:9: error: constructor cannot be instantiated to expected type;
found : (T1, T2, T3)
required: (Int, Int)
takesIntInt2Int { case (a, b, c) => a + b + c }
Like, srsly? o_O Both result in required: (Int, Int) error.
Why then use case at all in such anonymous functions?
See section 8.5 of the Scala reference (http://www.scala-lang.org/files/archive/nightly/pdfs/ScalaReference.pdf). The expression { case (a, b) => a + b } is interpreted differently based on the expected type. In your definition of f1 it created a PartialFunction[(Int, Int), Int] which was cast to a Function1[(Int, Int), Int], i.e. ((Int, Int)) => Int whereas in the definition of f2 it created a Function2[Int, Int, Int], i.e. (Int, Int) => Int.
These two interpretations relate to the two situations where you would commonly use case in an anonymous function.
One is for writing anonymous functions that accept tuples and work on their components, as you did with f1. An example would be the function you pass to the foreach or map method on a Map, e.g. Map(1 -> 2, 3 -> 4) map { case (k, v) => k + v }.
The second is for writing an anonymous function that does a match on its sole parameter. Your f2 is doing this, but not in any useful way. An example would be the anonymous function passed to collect, e.g. List(1, -2, 3) collect { case x if x > 0 => -x }.
Note that the two can be combined, that is functions like f1 can do complex matching as well. For example, Map(1 -> 2, 3 -> 4) collect { case (k, v) if k < 2 => v }.
Edit: res2 works because of tupling. If an application doesn't type check, the compiler will try wrapping the args in a tuple before failing.
But that is tried just for applications; it's not a general conversion, as you discovered. It will not try to upgrade a value Function2[A, B, C] to Function1[(A, B), C].