Is there a way to retrieve the arity of a function? For instance, given the following function:
def moop[I,O](func: I => O) = {
val arity = I.???
???
}
How would I get the arity of func?
If I is a tuple, you can call the productArity method on it which is inherited from Product.
If you have an object of which you only know it is some kind of function, you will have to check against the (finite) set of FunctionN classes since there is no common supertype as for tuples. It looks like we currently have Function0 up to Function22.
Related
I am looking at the PartialFunction source code of Scala. In the file, the trait PartialFunction as well as a companion object PartialFunction are defined. The companion object has methods cond and condOpt.
Link: https://github.com/othiym23/scala/blob/master/src/library/scala/PartialFunction.scala
When I look into andThen as well orElse function, the below method calls are present.
1. PartialFunction.this.isDefinedAt(x)
2. PartialFunction.this.apply(x)
I am not sure from where these functions (isDefinedAt / apply) are present.
Can someone please help where these two methods are present.
Thanks!
apply is defined on Function1, the parent class of PartialFunction (Note that A => B is syntax sugar for Function1[A, B]). isDefinedAt is defined directly on the PartialFunction trait. Note that both are abstract. If you write a function, you're responsible for determining what apply does. If you write a partial function, you're responsible for determining where it's defined.
isDefinedAt will often get magicked away by the compiler if you use partial function syntax. So if we write
val f: PartialFunction[Option[Int], Int] = { case Some(x) => x }
Then we can do
f.isDefinedAt(None) // false
f.isDefinedAt(Some(1)) // true
EDIT: Based on your comment, you're confused by PartialFunction.this.apply. Note the context in which this is executed.
new PartialFunction[A1, B1] {
def isDefinedAt(x: A1): Boolean =
PartialFunction.this.isDefinedAt(x) || that.isDefinedAt(x)
def apply(x: A1): B1 =
if (PartialFunction.this.isDefinedAt(x)) PartialFunction.this.apply(x)
else that.apply(x)
}
We're inside of a new anonymous object. this refers to that anonymous object. If we implemented apply in terms of this.apply, then it would be infinite recursion. Think of PartialFunction.this as being kind of like super, but rather than calling the superclass method, we're calling the concrete class method from inside of an anonymous instance.
I guess it's Function1 since PartialFunction extends A => B https://github.com/othiym23/scala/blob/master/src/library/scala/Function1.scala
I was watching John De Goes "FP to the Max" video. In the code he does something like this to get the implicit object:
object Program {
def apply[F[_]](implicit F: Program[F]): Program[F] = F
}
Does this imply that the variable name F (the first one in implicit F: Program[F]) is actually a different F? It is very confusing. Does he mean to do:
object Program {
def apply[F[_]](implicit ev: Program[F]): Program[F] = ev
}
How does the compile know which F he is referring to while returning the F? The type constructor or the variable in scope?
Indeed the function parameter T is different from type parameter T, for example
def f[T](T: T): T = T
f(42) // res0: Int = 42
Compiler does not get confused because values exist in a different universe from types:
...there exist two separate universes, the universe of types and the
universe of values. In the universe of values, we have methods which
take values as arguments in round parentheses (or occasionally curly
braces). In the universe of types, we have type constructors, which take types
as arguments in square brackets.
This convention is sometimes used when dealing with typeclasses. It is meant to communicate that we want to simply return the typeclass instance resolved for F. To avoid confusion you could use ev approach you already suggested in question, or even
object Program {
def apply[F[_]: Program]: Program[F] = implicitly[Program[F]]
}
As a side-note, this trick with apply method in companion object of typeclass allows us to avoid having to use implicitly, for example, given
trait Foo[T]
trait Bar[T]
trait Program[F[_]]
implicit val fooProgram: Program[Foo] = ???
implicit val barProgram: Program[Bar] = ???
object Program {
def apply[F[_]: Program]: Program[F] = implicitly
}
then we can write
Program[Bar]
instead of
implicitly[Program[Bar]]
How does the compile know which F he is referring to while returning the F? The type constructor or the variable in scope?
The compiler knows that a method/function can only return a value. So what follows the = has a type but is not a type.
I am new to Scala & trying to understand the Function Documentation for Scala in Spark. the 'flatMap' function has documentation like this
def
flatMap[U](f: (T) ⇒ TraversableOnce[U])(implicit arg0: ClassTag[U]): RDD[U]
Return a new RDD by first applying a function to all elements of this RDD, and then flattening the results.
Although I know what exactly flatMap does, understanding the documentation seems to be too Cryptic(with letter like U, f, T etc...). Would appreciate if someone can explain what exactly each part of this documentation conveys
def flatMap: this is a method called flatMap.
[U]: it's generic, with one type parameter, U.
(f: (T) ⇒ TraversableOnce[U]): it takes one argument, f, of type T ⇒ TraversableOnce[U] (T is the generic parameter of RDD itself, so e.g. if you have an RDD[String] then T = String). So f is a one-parameter function that takes a T and returns a TraversableOnce[U]. Remember that U is the type parameter (generic) on the method. So you can call this method with any function that takes T and returns TraversableOnce[Something].
(implicit arg0: ClassTag[U]): the method requires an implicit parameter of type ClassTag[U] to be available. Implicits like this often constrain what types a type parameter can be. In this case ClassTag means that the type U needs to have concrete type information available at compile time. In practice you can ignore this unless you're trying to call flatMap from a generic method of your own.
: RDD[U]: the method returns an RDD[U]. Remember U was the type parameter on the method. So if you call flatMap with an f that returns TraversableOnce[Int], the return type will be RDD[Int]; if you call flatMap with an f that returns TraversableOnce[Potato] the return type will be RDD[Potato], and so on.
def flatMap[U](f: (T) ⇒ TraversableOnce[U])(implicit arg0: ClassTag[U]): RDD[U]
Try replacing T with Person and U with Pet.
flatMap takes a function f as an argument. This function takes an instance of type Person as an argument, and returns a collection of Pets - i.e., that person's pets. flatMap will then return a single collection of Pets - i.e., RDD[Pet].
def flatMap[Pet](f: (Person) ⇒ TraversableOnce[Pet])(implicit arg0: ClassTag[Pet]): RDD[Pet]
//usage .
val allPets = people.flatMap(person => person.pets)
The implicit ClassTag on the second parameter list is a different story. That's used to ask the compiler to create a manifest for the type Pet, so that flatMap can reflect on the type.
Read more about it here: TypeTags and Manifests
I've tried this and it fails with error: missing parameter type for expanded function ((x$29) => x$29.sum).
Can someone please explain why this happens? Is this just that Scala's type inference is not powerful enough?
object HelloStackOverflow {
implicit class Repro[T](val iterable: Iterable[T]) extends AnyVal {
def foo[A, B, Z](bar: Iterable[B] => Z)(implicit evidence: T <:< (A, B)) =
bar(iterable.map(_._2))
}
List(("a", 1), ("b", 2)).foo(_.sum)
}
(using Scala 2.10)
Well this is because "The argument types of an anonymous function must be fully known" (Scala Language Specification 8.5).
When a method takes an anonymous function, scala uses the fact that it knows the type of the parameters to let the caller omit the types of the anonymous function's parameters (letting you write something like x => x+1 instead of x: Int => x+1, or _.sum instead of x: Iterable[Int] => x.sum. This is one of the nice applications of inference in scala. But obviously, this requires to know the exact expected type of the anonymous function in the first place, which is not the case here: the argument to the anonymous function bar is of type Iterable[B]. B is a free type variable that cannot in any way be inferred from earlier parameter lists (there is no previous parameter list in method foo).
So there is simply no way that the type of B in the anonymous function (_.sum) can be inferred, which triggers an error as knowing the exact type is mandated by the spec.
This is pretty logical. In scala, an anonymous function is just (like any function) an object. Creating an anonymous function means instantiating a generic class (that extends Function*), where the types of the function's parameter are encoded as type parameters of the Function* class (read it again, I promise this sentence makes sense). It is simply never possible to instantiate any generic class without fully specifying the type parameters. Functions are no exception.
As Impredicative showed in a comment, explicitly specifying the type of the anonymous function's parameter fixes the compile error:
List(("a", 1), ("b", 2)).foo((a : Iterable[Int]) => a.sum)
Or even:
List(("a", 1), ("b", 2)).foo((_.sum):Iterable[Int] => Int)
But in your case, it appears simple to fix the issue without having to explicitly specify the type of the anonymous function:
object HelloStackOverflow {
implicit class Repro[A,B](val iterable: Iterable[(A,B)]) extends AnyVal {
def foo[Z](bar: Iterable[B] => Z) =
bar(iterable.map(_._2))
}
List(("a", 1), ("b", 2)).foo(_.sum) // works like a charm
}
Maybe the reason why you used a single type parameter T (instead of parameters A and B as in my example above) with an evidence that T <: (A, B) was that in your real code you have other methods in class Repro that do not require T to be a pair. In this case, just create another implicit class Repro2 with a T type parameter, and migrate these other methods there. You don't need to put all your enrichments in the same implicit class.
How can I define a function that is accepting all the tuples(1 to 22) as argument, I have something as follows in mind:
def foo (v=Tuple) =...
foo((1,2))
foo((1,2,3))
EDIT:
To answer the comment: I am actually trying to create a Tensor class which is a set of values and a set of indices. The indices can be covariant and/or contravariant (cf Wikipedia1 and Wikipedia2). I wanted to have a special syntax like Tensor((1,2),(3,4),values) which would create a tensor with values, two covariant indices having length (2,3) and two contravariant indices with length (3,4). So using this syntax I could also write Tensor((1,2,3),3,values) (with an implicit Int=>Tuple1).
I agree that Tuples are not suitable for this, better to use Lists. However the syntax is not so nice then...
This really isn't what tuples are for (cf. the comments and answers here). Tuples are for doing things like returning multiple values from a method, where in Java you would have to create a lightweight class. If you have an arbitrary number of elements, you should use a collection.
Another way to provide a convenient API to your users (aside from implicit conversion) is to use multiple parameter lists with varargs:
def tensor(cov: Int*)(contrav: Int*)(values: Int*) = // ...
Your examples would be written
tensor(1,2)(3,4)(values)
tensor(1,2,3)(3)(values)
There is no trait specifically for tuples, but you could use a typeclass approach, as demonstrated in this answer.
If your goal is really to have a List but allow callers to pass in tuples (for convenience), you can modify that solution so that the type class produces a List rather than a Product.
In brief, the idea is that you provide implicit conversions from the types that callers can pass to the type you're actually going to use:
def foo(x: IndexList) = x.indices
sealed case class IndexList(indices: List[Int])
object IndexList {
implicit def val2indices(i: Int) = IndexList(List(i))
implicit def tuple2toIndices(t: (Int, Int)): IndexList =
product2indices(t)
// etc
implicit def list2indices(l: List[Int]) = IndexList(l)
private def product2indices(p: Product) =
IndexList(p.productIterator.toList.asInstanceOf[List[Int]])
}
You can then call your method with any type for which you've provided a conversion:
foo(1)
foo((2,3))
foo(List(1,2,3))
All case classes, including Tuples, extend scala.Product but unfortunately there's no marker trait specifically for tuples, so someone could sneak ordinary case classes into your method. Of course, there's no way to treat all arities in a uniform way and still be typesafe, but you can use productElement(n: Int) to extract the nth value, or productIterator to iterate over all the values.
But... This is heresy around here, but have you considered overloading? :)
What you probably want to use is an HList, not a tuple. An HList (heterogenous list) is basically an arbitrary-length, typed tuple.
There are a few examples of HLists in scala (they are not part of the standard library)
http://jnordenberg.blogspot.com/2008/08/hlist-in-scala.html
a great and comprehensive series by Mark Harrah (of SBT fame)
Miles Sabin's github examples, taken from his recent talk at Scala eXchange
Check this out. It actually works better than I expected ;)
scala> def f[T <: Product](x: T) = x
f: [T <: Product](x: T)T
scala> f(1)
<console>:9: error: inferred type arguments [Int] do not conform to method f's type parameter bounds [T <: Product]
scala> f(1, "2") // you don't even need the extra parenthesis
res0: (Int, java.lang.String) = (2,3)
scala> f(1, "2", BigInt("3"))
res1: (Int, java.lang.String, scala.math.BigInt) = (1,2,3)