scalaimplicithigher-kinded-typestype-constructorcontext-bound

Difference between [A: C] and [A[_]: C] context bounds


I'm a newbie, according to my lectures : class Test [T: Comparing] means that it requires an implicit value of type Comparing[T] that can be used in the methods of that class. With this Higher kinded type notation

Question : What does this expression def notation[F[_]: Sync] : F[Unit] = ??? refer to ?


Solution

  • Consider the difference between concrete type and type constructor

    Int         // concrete type
    List[Int]   // concrete type
    List        // type constructor
    

    We represent the shape of the type constructor using notation F[_]

    trait Foo[T]            // Foo takes any type
    trait Bar[F[_]]         // Bar takes any type constructor
    
    new Foo[Int] {}         // ok
    new Foo[List[Int]] {}   // ok
    new Foo[List] {}        // error
    
    new Bar[Int] {}         // error
    new Bar[List[Int]] {}   // error 
    new Bar[List] {}        // ok
    

    We could read type parameter clause [F[_]: Bar] as meaning

    trait Bar[F[_]]
    
    // make type constructor Foo a member of typeclass Bar
    implicit val barOfFoo: Bar[Foo] = new Bar[Foo] { println("woohoo") }
    
    def g[F[_]: Bar] = implicitly[Bar[F]]
    
    g[Foo]        // ok
    g[Int]        // error - type parameter is of incorrect shape
    g[Foo[Int]]   // error - type parameter is of incorrect shape
    g[List]       // error - type parameter is of correct shape but not a member of Bar
    

    Applying the above concepts to def notation[F[_]: Sync] we see that type constructor F has to be a member of typeclass Sync in order to call notation.