How to import implicits implicitly when defined in an object thats passed as a parameter

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

How to import implicits implicitly when defined in an object thats passed as a parameter

Hugo Ferreira
Hello,

I read part of the shapeless guide (chapter 7) that describes the use of `Poly`.
In chapter 7 it states:

"There is some subtle scoping behaviour here that allows the compiler to lo-
cate instances of Case without any additional imports. Case has an extra type
parameter P referencing the singleton type of the Poly . The implicit scope
for Case[P, A] includes the companion objects for Case , P , and A . We’ve as-
signed P to be myPoly.type and the companion object for myPoly.type is
myPoly itself. In other words, Cases defined in the body of the Poly are al-
ways in scope no matter where the call site is."

So I created my version of Poly so:

trait Case[P, A] {
  type Result
  def apply(a: A): Result
}

trait Poly {
  def apply[A](arg: A)(implicit cse: Case[this.type, A] ): cse.Result = cse.apply( arg )
}

I then implemented an instance of Poly so:

 object myPoly extends Poly {
    implicit def intCase = {
      new Case[this.type, Int] {
        type Result = Double
        def apply(num: Int): Double = num / 2.0
      }
    }

    implicit def stringCase = {
      new Case[ this.type, String ] {
        type Result = Int
        def apply( str: String ): Int = str.length
      }
    }
  }

And did some very basic tests that worked:

    val p1 = myPoly( 123 )
    println( s"Poly(123) = $p1" )
    val p2 = myPoly.apply( "456" )
    println( s"Poly('123') = $p2" )

Now I tried to pass myPoly as a parameter as is done in scalaz to "process"
some elements in an HList. So I have defined these initial test:

    // Nothing new here
    def callPoly1( a: Int, b: String) = {
      val v1 = myPoly( a )
      val v2 = myPoly( b )
      (v1, v2)
    }

    // As expected, companion object in scope
    def callPoly2( a: Int, b: String)( implicit cse1: Case[ _, Int ], cse2: Case[ _, String ] ) = {
      val v1 = cse1( a )
      val v2 = cse2( b )
      (v1, v2)
    }

    def callPoly3( a: Int, b: String, p: Poly ) = {
      val t0 = implicitly[Case[ myPoly.type, Int ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v1 = t0( a )
      val t1 = implicitly[Case[ myPoly.type, String ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v2 = t1( b )
      (v1, v2)
    }

which are called so:

    // Ok
    callPoly1( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly2( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly3( 1, "2", myPoly)

So far so good. Now I try this:

    def callPoly( a: Int, b: String, p: Poly ) = {
      //import p.apply
      import p._
      //import myPoly._
      //val t1 = implicitly[Case[ p.type, String ] ]
     
      val v5 = p(a)
    }

But get the compilation error:

could not find implicit value for parameter cse: Case[p.type,Int]
[error]       val v5 = p(a)
[error]                      ^
[error] one error found

I tried the most obvious means of importing the definitions of the implicits but have not succeeded.
It seems I need the myPoly.type but how do I get this if I can only pass in a Poly? A look at the scalaz
code shows that a Mapper is used, but I cannot decipher how that uses the FP parameter to bring in
the implicits into scope.

Can anyone tell me how to do this? I have looked at [1] and found no reference to this technique.

TIA

1. http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to import implicits implicitly when defined in an object thats passed as a parameter

Jasper-M
I'm no expert, but I think you should always ask for the required Cases in the implicit parameter list of your methods.
Probably clearer with an example:

scala> def callPoly( a: Int, b: String, p: Poly )(implicit intCase: Case[p.type,Int], strCase: Case[p.type,String]) = {
     |   val v1 = p(a)
     |   val v2 = p(b) 
     |   (v1, v2)
     | }
callPoly: (a: Int, b: String, p: Poly)(implicit intCase: Case[p.type,Int], implicit strCase: Case[p.type,String])(intCase.Result, strCase.Result)

scala> callPoly(3,"foobar", myPoly)
res2: (Double, Int) = (1.5,6)


Op donderdag 12 januari 2017 17:49:22 UTC+1 schreef Hugo Ferreira:
Hello,

I read part of the shapeless guide (chapter 7) that describes the use of `Poly`.
In chapter 7 it states:

"There is some subtle scoping behaviour here that allows the compiler to lo-
cate instances of Case without any additional imports. Case has an extra type
parameter P referencing the singleton type of the Poly . The implicit scope
for Case[P, A] includes the companion objects for Case , P , and A . We’ve as-
signed P to be myPoly.type and the companion object for myPoly.type is
myPoly itself. In other words, Cases defined in the body of the Poly are al-
ways in scope no matter where the call site is."

So I created my version of Poly so:

trait Case[P, A] {
  type Result
  def apply(a: A): Result
}

trait Poly {
  def apply[A](arg: A)(implicit cse: Case[this.type, A] ): cse.Result = cse.apply( arg )
}

I then implemented an instance of Poly so:

 object myPoly extends Poly {
    implicit def intCase = {
      new Case[this.type, Int] {
        type Result = Double
        def apply(num: Int): Double = num / 2.0
      }
    }

    implicit def stringCase = {
      new Case[ this.type, String ] {
        type Result = Int
        def apply( str: String ): Int = str.length
      }
    }
  }

And did some very basic tests that worked:

    val p1 = myPoly( 123 )
    println( s"Poly(123) = $p1" )
    val p2 = myPoly.apply( "456" )
    println( s"Poly('123') = $p2" )

Now I tried to pass myPoly as a parameter as is done in scalaz to "process"
some elements in an HList. So I have defined these initial test:

    // Nothing new here
    def callPoly1( a: Int, b: String) = {
      val v1 = myPoly( a )
      val v2 = myPoly( b )
      (v1, v2)
    }

    // As expected, companion object in scope
    def callPoly2( a: Int, b: String)( implicit cse1: Case[ _, Int ], cse2: Case[ _, String ] ) = {
      val v1 = cse1( a )
      val v2 = cse2( b )
      (v1, v2)
    }

    def callPoly3( a: Int, b: String, p: Poly ) = {
      val t0 = implicitly[Case[ myPoly.type, Int ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v1 = t0( a )
      val t1 = implicitly[Case[ myPoly.type, String ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v2 = t1( b )
      (v1, v2)
    }

which are called so:

    // Ok
    callPoly1( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly2( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly3( 1, "2", myPoly)

So far so good. Now I try this:

    def callPoly( a: Int, b: String, p: Poly ) = {
      //import p.apply
      import p._
      //import myPoly._
      //val t1 = implicitly[Case[ p.type, String ] ]
     
      val v5 = p(a)
    }

But get the compilation error:

could not find implicit value for parameter cse: Case[p.type,Int]
[error]       val v5 = p(a)
[error]                      ^
[error] one error found

I tried the most obvious means of importing the definitions of the implicits but have not succeeded.
It seems I need the myPoly.type but how do I get this if I can only pass in a Poly? A look at the scalaz
code shows that a Mapper is used, but I cannot decipher how that uses the FP parameter to bring in
the implicits into scope.

Can anyone tell me how to do this? I have looked at [1] and found no reference to this technique.

TIA

1. <a href="http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fdocs.scala-lang.org%2Ftutorials%2FFAQ%2Ffinding-implicits.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF--5RVAixi6rJ9PQSjwnQowJK3HQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fdocs.scala-lang.org%2Ftutorials%2FFAQ%2Ffinding-implicits.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF--5RVAixi6rJ9PQSjwnQowJK3HQ&#39;;return true;">http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to import implicits implicitly when defined in an object thats passed as a parameter

Hugo Ferreira

Thank you. That works.

I also tried using "implicitly" but that doe not work. I am assuming
that using implicitly or declaring it via a parameter should be equivalent.
Am I wrong? If not why does this not work:

def callPoly6( a: Int, b: String, p: Poly) = {
      val t0 = implicitly[ Case[ p.type, Int ] ]
      val v1 = t0( a )
      val t1 = implicitly[ Case[ p.type, String ] ]
      val v2 = t1( b )
      ( v1, v2 )
    }

I get:

 could not find implicit value for parameter e: Case[p.type,String]
[error]       val t1 = implicitly[ Case[ p.type, String ] ]

I have tried various variants to no effect by using alternate definitions such as:

    def implicitlyPoly[T[_,_] , A, B](implicit e: T[A,B]) = e
    def implicitlyPoly[A, B](implicit e: Case[A,B]) = e
    def implicitlyPoly[A](p:Poly)(implicit e: Case[p.type,A]) = e
    def implicitlyPoly(p:Poly)(implicit e: Case[p.type,Int]) = e
    def implicitlyPoly(v: Int, p:Poly)(implicit e: Case[p.type,Int]) = p(v)

Any suggestions?

TIA



On Friday, 13 January 2017 08:54:27 UTC, Jasper-M wrote:
I'm no expert, but I think you should always ask for the required Cases in the implicit parameter list of your methods.
Probably clearer with an example:

scala> def callPoly( a: Int, b: String, p: Poly )(implicit intCase: Case[p.type,Int], strCase: Case[p.type,String]) = {
     |   val v1 = p(a)
     |   val v2 = p(b) 
     |   (v1, v2)
     | }
callPoly: (a: Int, b: String, p: Poly)(implicit intCase: Case[p.type,Int], implicit strCase: Case[p.type,String])(intCase.Result, strCase.Result)

scala> callPoly(3,"foobar", myPoly)
res2: (Double, Int) = (1.5,6)


Op donderdag 12 januari 2017 17:49:22 UTC+1 schreef Hugo Ferreira:
Hello,

I read part of the shapeless guide (chapter 7) that describes the use of `Poly`.
In chapter 7 it states:

"There is some subtle scoping behaviour here that allows the compiler to lo-
cate instances of Case without any additional imports. Case has an extra type
parameter P referencing the singleton type of the Poly . The implicit scope
for Case[P, A] includes the companion objects for Case , P , and A . We’ve as-
signed P to be myPoly.type and the companion object for myPoly.type is
myPoly itself. In other words, Cases defined in the body of the Poly are al-
ways in scope no matter where the call site is."

So I created my version of Poly so:

trait Case[P, A] {
  type Result
  def apply(a: A): Result
}

trait Poly {
  def apply[A](arg: A)(implicit cse: Case[this.type, A] ): cse.Result = cse.apply( arg )
}

I then implemented an instance of Poly so:

 object myPoly extends Poly {
    implicit def intCase = {
      new Case[this.type, Int] {
        type Result = Double
        def apply(num: Int): Double = num / 2.0
      }
    }

    implicit def stringCase = {
      new Case[ this.type, String ] {
        type Result = Int
        def apply( str: String ): Int = str.length
      }
    }
  }

And did some very basic tests that worked:

    val p1 = myPoly( 123 )
    println( s"Poly(123) = $p1" )
    val p2 = myPoly.apply( "456" )
    println( s"Poly('123') = $p2" )

Now I tried to pass myPoly as a parameter as is done in scalaz to "process"
some elements in an HList. So I have defined these initial test:

    // Nothing new here
    def callPoly1( a: Int, b: String) = {
      val v1 = myPoly( a )
      val v2 = myPoly( b )
      (v1, v2)
    }

    // As expected, companion object in scope
    def callPoly2( a: Int, b: String)( implicit cse1: Case[ _, Int ], cse2: Case[ _, String ] ) = {
      val v1 = cse1( a )
      val v2 = cse2( b )
      (v1, v2)
    }

    def callPoly3( a: Int, b: String, p: Poly ) = {
      val t0 = implicitly[Case[ myPoly.type, Int ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v1 = t0( a )
      val t1 = implicitly[Case[ myPoly.type, String ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v2 = t1( b )
      (v1, v2)
    }

which are called so:

    // Ok
    callPoly1( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly2( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly3( 1, "2", myPoly)

So far so good. Now I try this:

    def callPoly( a: Int, b: String, p: Poly ) = {
      //import p.apply
      import p._
      //import myPoly._
      //val t1 = implicitly[Case[ p.type, String ] ]
     
      val v5 = p(a)
    }

But get the compilation error:

could not find implicit value for parameter cse: Case[p.type,Int]
[error]       val v5 = p(a)
[error]                      ^
[error] one error found

I tried the most obvious means of importing the definitions of the implicits but have not succeeded.
It seems I need the myPoly.type but how do I get this if I can only pass in a Poly? A look at the scalaz
code shows that a Mapper is used, but I cannot decipher how that uses the FP parameter to bring in
the implicits into scope.

Can anyone tell me how to do this? I have looked at [1] and found no reference to this technique.

TIA

1. <a href="http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fdocs.scala-lang.org%2Ftutorials%2FFAQ%2Ffinding-implicits.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF--5RVAixi6rJ9PQSjwnQowJK3HQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fdocs.scala-lang.org%2Ftutorials%2FFAQ%2Ffinding-implicits.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF--5RVAixi6rJ9PQSjwnQowJK3HQ&#39;;return true;">http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to import implicits implicitly when defined in an object thats passed as a parameter

Hugo Ferreira
Hello,

After some more digging... I have also noticed the following:
we seem to need to propagate the implicit through all of the call stack.
So in the example bellow, if we don't add the implicits, compilation will fail.

    def callCallPoly( a: Int, b: String, p: Poly)( implicit cse1: Case[ p.type, Int ], cse2: Case[ p.type, String ] ) = {
      callPoly( a, b, p)
    }

This seems to be the issue that is causing the problem with the `implicilty` construct.
Is their any way we can circumvent this? The only solution I have come up with is to
implicitly get the `Case`at the top most call and then pass these on instead of the poly.

TIA

On Friday, 13 January 2017 10:55:21 UTC, Hugo Ferreira wrote:

Thank you. That works.

I also tried using "implicitly" but that doe not work. I am assuming
that using implicitly or declaring it via a parameter should be equivalent.
Am I wrong? If not why does this not work:

def callPoly6( a: Int, b: String, p: Poly) = {
      val t0 = implicitly[ Case[ p.type, Int ] ]
      val v1 = t0( a )
      val t1 = implicitly[ Case[ p.type, String ] ]
      val v2 = t1( b )
      ( v1, v2 )
    }

I get:

 could not find implicit value for parameter e: Case[p.type,String]
[error]       val t1 = implicitly[ Case[ p.type, String ] ]

I have tried various variants to no effect by using alternate definitions such as:

    def implicitlyPoly[T[_,_] , A, B](implicit e: T[A,B]) = e
    def implicitlyPoly[A, B](implicit e: Case[A,B]) = e
    def implicitlyPoly[A](p:Poly)(implicit e: Case[p.type,A]) = e
    def implicitlyPoly(p:Poly)(implicit e: Case[p.type,Int]) = e
    def implicitlyPoly(v: Int, p:Poly)(implicit e: Case[p.type,Int]) = p(v)

Any suggestions?

TIA



On Friday, 13 January 2017 08:54:27 UTC, Jasper-M wrote:
I'm no expert, but I think you should always ask for the required Cases in the implicit parameter list of your methods.
Probably clearer with an example:

scala> def callPoly( a: Int, b: String, p: Poly )(implicit intCase: Case[p.type,Int], strCase: Case[p.type,String]) = {
     |   val v1 = p(a)
     |   val v2 = p(b) 
     |   (v1, v2)
     | }
callPoly: (a: Int, b: String, p: Poly)(implicit intCase: Case[p.type,Int], implicit strCase: Case[p.type,String])(intCase.Result, strCase.Result)

scala> callPoly(3,"foobar", myPoly)
res2: (Double, Int) = (1.5,6)


Op donderdag 12 januari 2017 17:49:22 UTC+1 schreef Hugo Ferreira:
Hello,

I read part of the shapeless guide (chapter 7) that describes the use of `Poly`.
In chapter 7 it states:

"There is some subtle scoping behaviour here that allows the compiler to lo-
cate instances of Case without any additional imports. Case has an extra type
parameter P referencing the singleton type of the Poly . The implicit scope
for Case[P, A] includes the companion objects for Case , P , and A . We’ve as-
signed P to be myPoly.type and the companion object for myPoly.type is
myPoly itself. In other words, Cases defined in the body of the Poly are al-
ways in scope no matter where the call site is."

So I created my version of Poly so:

trait Case[P, A] {
  type Result
  def apply(a: A): Result
}

trait Poly {
  def apply[A](arg: A)(implicit cse: Case[this.type, A] ): cse.Result = cse.apply( arg )
}

I then implemented an instance of Poly so:

 object myPoly extends Poly {
    implicit def intCase = {
      new Case[this.type, Int] {
        type Result = Double
        def apply(num: Int): Double = num / 2.0
      }
    }

    implicit def stringCase = {
      new Case[ this.type, String ] {
        type Result = Int
        def apply( str: String ): Int = str.length
      }
    }
  }

And did some very basic tests that worked:

    val p1 = myPoly( 123 )
    println( s"Poly(123) = $p1" )
    val p2 = myPoly.apply( "456" )
    println( s"Poly('123') = $p2" )

Now I tried to pass myPoly as a parameter as is done in scalaz to "process"
some elements in an HList. So I have defined these initial test:

    // Nothing new here
    def callPoly1( a: Int, b: String) = {
      val v1 = myPoly( a )
      val v2 = myPoly( b )
      (v1, v2)
    }

    // As expected, companion object in scope
    def callPoly2( a: Int, b: String)( implicit cse1: Case[ _, Int ], cse2: Case[ _, String ] ) = {
      val v1 = cse1( a )
      val v2 = cse2( b )
      (v1, v2)
    }

    def callPoly3( a: Int, b: String, p: Poly ) = {
      val t0 = implicitly[Case[ myPoly.type, Int ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v1 = t0( a )
      val t1 = implicitly[Case[ myPoly.type, String ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v2 = t1( b )
      (v1, v2)
    }

which are called so:

    // Ok
    callPoly1( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly2( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly3( 1, "2", myPoly)

So far so good. Now I try this:

    def callPoly( a: Int, b: String, p: Poly ) = {
      //import p.apply
      import p._
      //import myPoly._
      //val t1 = implicitly[Case[ p.type, String ] ]
     
      val v5 = p(a)
    }

But get the compilation error:

could not find implicit value for parameter cse: Case[p.type,Int]
[error]       val v5 = p(a)
[error]                      ^
[error] one error found

I tried the most obvious means of importing the definitions of the implicits but have not succeeded.
It seems I need the myPoly.type but how do I get this if I can only pass in a Poly? A look at the scalaz
code shows that a Mapper is used, but I cannot decipher how that uses the FP parameter to bring in
the implicits into scope.

Can anyone tell me how to do this? I have looked at [1] and found no reference to this technique.

TIA

1. <a href="http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fdocs.scala-lang.org%2Ftutorials%2FFAQ%2Ffinding-implicits.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF--5RVAixi6rJ9PQSjwnQowJK3HQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fdocs.scala-lang.org%2Ftutorials%2FFAQ%2Ffinding-implicits.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF--5RVAixi6rJ9PQSjwnQowJK3HQ&#39;;return true;">http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to import implicits implicitly when defined in an object thats passed as a parameter

Jasper-M
In reply to this post by Hugo Ferreira
Implicitly is actually just a method defined in scala.Predef: def implicitly[T](implicit e: T) = e
Inside your method callPoly6 the knowledge that p.type =:= myPoly.type is already lost. And that is exactly the knowledge that implicit search needs. Without it the compiler has no clue it has to go looking in the myPoly object for those implicit Cases.

The only place where the compiler knows that p.type =:= myPoly.type is where you actually do the the call callPoly6(???, ???, myPoly). So that is where you should ask the compiler to go looking for your implicit Cases. And you do that by giving your method an implicit parameter list. There's no way around it.

Op vrijdag 13 januari 2017 11:55:21 UTC+1 schreef Hugo Ferreira:

Thank you. That works.

I also tried using "implicitly" but that doe not work. I am assuming
that using implicitly or declaring it via a parameter should be equivalent.
Am I wrong? If not why does this not work:

def callPoly6( a: Int, b: String, p: Poly) = {
      val t0 = implicitly[ Case[ p.type, Int ] ]
      val v1 = t0( a )
      val t1 = implicitly[ Case[ p.type, String ] ]
      val v2 = t1( b )
      ( v1, v2 )
    }

I get:

 could not find implicit value for parameter e: Case[p.type,String]
[error]       val t1 = implicitly[ Case[ p.type, String ] ]

I have tried various variants to no effect by using alternate definitions such as:

    def implicitlyPoly[T[_,_] , A, B](implicit e: T[A,B]) = e
    def implicitlyPoly[A, B](implicit e: Case[A,B]) = e
    def implicitlyPoly[A](p:Poly)(implicit e: Case[p.type,A]) = e
    def implicitlyPoly(p:Poly)(implicit e: Case[p.type,Int]) = e
    def implicitlyPoly(v: Int, p:Poly)(implicit e: Case[p.type,Int]) = p(v)

Any suggestions?

TIA



On Friday, 13 January 2017 08:54:27 UTC, Jasper-M wrote:
I'm no expert, but I think you should always ask for the required Cases in the implicit parameter list of your methods.
Probably clearer with an example:

scala> def callPoly( a: Int, b: String, p: Poly )(implicit intCase: Case[p.type,Int], strCase: Case[p.type,String]) = {
     |   val v1 = p(a)
     |   val v2 = p(b) 
     |   (v1, v2)
     | }
callPoly: (a: Int, b: String, p: Poly)(implicit intCase: Case[p.type,Int], implicit strCase: Case[p.type,String])(intCase.Result, strCase.Result)

scala> callPoly(3,"foobar", myPoly)
res2: (Double, Int) = (1.5,6)


Op donderdag 12 januari 2017 17:49:22 UTC+1 schreef Hugo Ferreira:
Hello,

I read part of the shapeless guide (chapter 7) that describes the use of `Poly`.
In chapter 7 it states:

"There is some subtle scoping behaviour here that allows the compiler to lo-
cate instances of Case without any additional imports. Case has an extra type
parameter P referencing the singleton type of the Poly . The implicit scope
for Case[P, A] includes the companion objects for Case , P , and A . We’ve as-
signed P to be myPoly.type and the companion object for myPoly.type is
myPoly itself. In other words, Cases defined in the body of the Poly are al-
ways in scope no matter where the call site is."

So I created my version of Poly so:

trait Case[P, A] {
  type Result
  def apply(a: A): Result
}

trait Poly {
  def apply[A](arg: A)(implicit cse: Case[this.type, A] ): cse.Result = cse.apply( arg )
}

I then implemented an instance of Poly so:

 object myPoly extends Poly {
    implicit def intCase = {
      new Case[this.type, Int] {
        type Result = Double
        def apply(num: Int): Double = num / 2.0
      }
    }

    implicit def stringCase = {
      new Case[ this.type, String ] {
        type Result = Int
        def apply( str: String ): Int = str.length
      }
    }
  }

And did some very basic tests that worked:

    val p1 = myPoly( 123 )
    println( s"Poly(123) = $p1" )
    val p2 = myPoly.apply( "456" )
    println( s"Poly('123') = $p2" )

Now I tried to pass myPoly as a parameter as is done in scalaz to "process"
some elements in an HList. So I have defined these initial test:

    // Nothing new here
    def callPoly1( a: Int, b: String) = {
      val v1 = myPoly( a )
      val v2 = myPoly( b )
      (v1, v2)
    }

    // As expected, companion object in scope
    def callPoly2( a: Int, b: String)( implicit cse1: Case[ _, Int ], cse2: Case[ _, String ] ) = {
      val v1 = cse1( a )
      val v2 = cse2( b )
      (v1, v2)
    }

    def callPoly3( a: Int, b: String, p: Poly ) = {
      val t0 = implicitly[Case[ myPoly.type, Int ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v1 = t0( a )
      val t1 = implicitly[Case[ myPoly.type, String ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v2 = t1( b )
      (v1, v2)
    }

which are called so:

    // Ok
    callPoly1( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly2( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly3( 1, "2", myPoly)

So far so good. Now I try this:

    def callPoly( a: Int, b: String, p: Poly ) = {
      //import p.apply
      import p._
      //import myPoly._
      //val t1 = implicitly[Case[ p.type, String ] ]
     
      val v5 = p(a)
    }

But get the compilation error:

could not find implicit value for parameter cse: Case[p.type,Int]
[error]       val v5 = p(a)
[error]                      ^
[error] one error found

I tried the most obvious means of importing the definitions of the implicits but have not succeeded.
It seems I need the myPoly.type but how do I get this if I can only pass in a Poly? A look at the scalaz
code shows that a Mapper is used, but I cannot decipher how that uses the FP parameter to bring in
the implicits into scope.

Can anyone tell me how to do this? I have looked at [1] and found no reference to this technique.

TIA

1. <a href="http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fdocs.scala-lang.org%2Ftutorials%2FFAQ%2Ffinding-implicits.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF--5RVAixi6rJ9PQSjwnQowJK3HQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fdocs.scala-lang.org%2Ftutorials%2FFAQ%2Ffinding-implicits.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF--5RVAixi6rJ9PQSjwnQowJK3HQ&#39;;return true;">http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: How to import implicits implicitly when defined in an object thats passed as a parameter

Hugo Ferreira
Jasper,

Appreciate the feedback.

On Friday, 13 January 2017 15:34:47 UTC, Jasper-M wrote:
Implicitly is actually just a method defined in scala.Predef: def implicitly[T](implicit e: T) = e

Yes. I tried several variants of this function in my experiments.
 

Inside your method callPoly6 the knowledge that p.type =:= myPoly.type is already lost. And that is exactly the knowledge that implicit search needs. Without it the compiler has no clue it has to go looking in the myPoly object for those implicit Cases.


That's what was so confusing. In the call I am passing a Poly, not a myPoly. When I call implicitly[] I am still passing on a Poly.
It seemed like the compiler was loosing type information when passing the reference from one call to another. Not so. Now I
see that all of the "original" typing are available at the call, later (inside the functions) only the types as declared in the parameter
list are available.

The only place where the compiler knows that p.type =:= myPoly.type is where you actually do the the call callPoly6(???, ???, myPoly). So that is where you should ask the compiler to go looking for your implicit Cases. And you do that by giving your method an implicit parameter list. There's no way around it.


I was assuming that the use of Scalaz's Poly did not suffer from the problem, maybe with some black art thingy B-).
Ok, this makes sense now.

Thank you. 

Op vrijdag 13 januari 2017 11:55:21 UTC+1 schreef Hugo Ferreira:

Thank you. That works.

I also tried using "implicitly" but that doe not work. I am assuming
that using implicitly or declaring it via a parameter should be equivalent.
Am I wrong? If not why does this not work:

def callPoly6( a: Int, b: String, p: Poly) = {
      val t0 = implicitly[ Case[ p.type, Int ] ]
      val v1 = t0( a )
      val t1 = implicitly[ Case[ p.type, String ] ]
      val v2 = t1( b )
      ( v1, v2 )
    }

I get:

 could not find implicit value for parameter e: Case[p.type,String]
[error]       val t1 = implicitly[ Case[ p.type, String ] ]

I have tried various variants to no effect by using alternate definitions such as:

    def implicitlyPoly[T[_,_] , A, B](implicit e: T[A,B]) = e
    def implicitlyPoly[A, B](implicit e: Case[A,B]) = e
    def implicitlyPoly[A](p:Poly)(implicit e: Case[p.type,A]) = e
    def implicitlyPoly(p:Poly)(implicit e: Case[p.type,Int]) = e
    def implicitlyPoly(v: Int, p:Poly)(implicit e: Case[p.type,Int]) = p(v)

Any suggestions?

TIA



On Friday, 13 January 2017 08:54:27 UTC, Jasper-M wrote:
I'm no expert, but I think you should always ask for the required Cases in the implicit parameter list of your methods.
Probably clearer with an example:

scala> def callPoly( a: Int, b: String, p: Poly )(implicit intCase: Case[p.type,Int], strCase: Case[p.type,String]) = {
     |   val v1 = p(a)
     |   val v2 = p(b) 
     |   (v1, v2)
     | }
callPoly: (a: Int, b: String, p: Poly)(implicit intCase: Case[p.type,Int], implicit strCase: Case[p.type,String])(intCase.Result, strCase.Result)

scala> callPoly(3,"foobar", myPoly)
res2: (Double, Int) = (1.5,6)


Op donderdag 12 januari 2017 17:49:22 UTC+1 schreef Hugo Ferreira:
Hello,

I read part of the shapeless guide (chapter 7) that describes the use of `Poly`.
In chapter 7 it states:

"There is some subtle scoping behaviour here that allows the compiler to lo-
cate instances of Case without any additional imports. Case has an extra type
parameter P referencing the singleton type of the Poly . The implicit scope
for Case[P, A] includes the companion objects for Case , P , and A . We’ve as-
signed P to be myPoly.type and the companion object for myPoly.type is
myPoly itself. In other words, Cases defined in the body of the Poly are al-
ways in scope no matter where the call site is."

So I created my version of Poly so:

trait Case[P, A] {
  type Result
  def apply(a: A): Result
}

trait Poly {
  def apply[A](arg: A)(implicit cse: Case[this.type, A] ): cse.Result = cse.apply( arg )
}

I then implemented an instance of Poly so:

 object myPoly extends Poly {
    implicit def intCase = {
      new Case[this.type, Int] {
        type Result = Double
        def apply(num: Int): Double = num / 2.0
      }
    }

    implicit def stringCase = {
      new Case[ this.type, String ] {
        type Result = Int
        def apply( str: String ): Int = str.length
      }
    }
  }

And did some very basic tests that worked:

    val p1 = myPoly( 123 )
    println( s"Poly(123) = $p1" )
    val p2 = myPoly.apply( "456" )
    println( s"Poly('123') = $p2" )

Now I tried to pass myPoly as a parameter as is done in scalaz to "process"
some elements in an HList. So I have defined these initial test:

    // Nothing new here
    def callPoly1( a: Int, b: String) = {
      val v1 = myPoly( a )
      val v2 = myPoly( b )
      (v1, v2)
    }

    // As expected, companion object in scope
    def callPoly2( a: Int, b: String)( implicit cse1: Case[ _, Int ], cse2: Case[ _, String ] ) = {
      val v1 = cse1( a )
      val v2 = cse2( b )
      (v1, v2)
    }

    def callPoly3( a: Int, b: String, p: Poly ) = {
      val t0 = implicitly[Case[ myPoly.type, Int ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v1 = t0( a )
      val t1 = implicitly[Case[ myPoly.type, String ] ] // The self-referincing of the this.type allows us to avoid importing the implicits
      val v2 = t1( b )
      (v1, v2)
    }

which are called so:

    // Ok
    callPoly1( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly2( 1, "2")
   
    // Needs import
    import myPoly._
    //callPoly3( 1, "2", myPoly)

So far so good. Now I try this:

    def callPoly( a: Int, b: String, p: Poly ) = {
      //import p.apply
      import p._
      //import myPoly._
      //val t1 = implicitly[Case[ p.type, String ] ]
     
      val v5 = p(a)
    }

But get the compilation error:

could not find implicit value for parameter cse: Case[p.type,Int]
[error]       val v5 = p(a)
[error]                      ^
[error] one error found

I tried the most obvious means of importing the definitions of the implicits but have not succeeded.
It seems I need the myPoly.type but how do I get this if I can only pass in a Poly? A look at the scalaz
code shows that a Mapper is used, but I cannot decipher how that uses the FP parameter to bring in
the implicits into scope.

Can anyone tell me how to do this? I have looked at [1] and found no reference to this technique.

TIA

1. <a href="http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fdocs.scala-lang.org%2Ftutorials%2FFAQ%2Ffinding-implicits.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF--5RVAixi6rJ9PQSjwnQowJK3HQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fdocs.scala-lang.org%2Ftutorials%2FFAQ%2Ffinding-implicits.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF--5RVAixi6rJ9PQSjwnQowJK3HQ&#39;;return true;">http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.