Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does foo[F[_], A](ff: F[A]) accept foo(1)?

Why does the call to foo(1) work in my Scala 2.11.7 repl as described below?

scala> def foo[F[_], A](fa: F[A]) = null
foo: [F[_], A](fa: F[A])Null

scala> foo(List(1))
res0: Null = null

scala> foo(1)
res1: Null = null

The parameter in my call to foo(1) is not a Type Constructor so why does the Scala repl accept it?

like image 708
Rob O'Doherty Avatar asked Jan 17 '16 13:01

Rob O'Doherty


2 Answers

Your Int is considered an instance of class Any (because is not a type constructor and so type hierarchy is analyzed to find a supertype that is also a type constructor), and class Any in Scala is considered a type constructor of type Nothing.

You can check this behavior with following code:

import scala.reflect.runtime.universe._

object Main {
  def foo[F[_], A](fa: F[A])(implicit ev: TypeTag[F[A]], ev2: TypeTag[A]) = {
    println(ev)
    println(ev2)
    println(ev.tpe.typeArgs)
    println()
    null
  }

  def main(args: Array[String]){
    foo(List(1))
    foo(1)
  }
}

Output:

TypeTag[List[Int]]
TypeTag[Int]
List(Int)

TypeTag[Any]
TypeTag[Nothing]
List()
like image 133
Vincenzo Maggio Avatar answered Oct 30 '22 05:10

Vincenzo Maggio


foo(1) works because there is an implicit conversion int2Integer to java.lang.Integer

foo(int2Integer(1))

and Integer is an instance of Comparable[Integer]

public final class Integer extends Number implements Comparable<Integer>

where we see Comparable is indeed a type constructor. For example, we can reproduce the same behaviour like so

def foo[F[_], A](fa: F[A]) = 42
trait Bar // not a type constructor
implicit def barToComparable(b: Bar): Comparable[Int] = (o: Int) => -1
val bar = new Bar {}
foo(bar) // OK due to implicit conversion barToComparable
like image 45
Mario Galic Avatar answered Oct 30 '22 04:10

Mario Galic