# What constraints to add to ensure invariance - compiler infers Any instead of String Classic List Threaded 6 messages Open this post in threaded view
|

## What constraints to add to ensure invariance - compiler infers Any instead of String

 Hello,I have the following very basic code:  trait Parameter[ T ] {    type Self <: Parameter[ T ]    def apply( v: T ): Self  }  import scala.language.higherKinds  case class ParameterRange[ P[ X ] <: Parameter[ X ], T, U ](      val param: P[ T ],      val start: T,      val stop: T,      val config: U ){    def toStream( f: ( T, T, U ) => Stream[ T ] ): Stream[ P[ T ]#Self ] = {      val st = f( start, stop, config )      val r = st.map{ x: T => param( x ) }      r    }  }If I use an Int as the Parameter type I have no problems:  case class Param1( v: Int ) extends Parameter[ Int ] { type Self = Param1; def apply( v: Int ) = new Param1( v ) }  val p1 = Param1( 0 )  val pr1 = ParameterRange( p1, 0, 10, 1 )  val p2 = Param1( 1 )  val pr2 = ParameterRange( p2, 0, 10, 1 )But if I use a string:  case class Param3( v: String ) extends Parameter[ String ] { type Self = Param3; def apply( v: String ) = new Param3( v ) }  val p3 : Parameter[String] = Param3( "" )  val pr3  = ParameterRange( p3, 0, 10, 1 )I get an error:[error]  found   : NonConformanceToType.Parameter[String][error]  required: NonConformanceToType.Parameter[Any][error] Note: String <: Any, but trait Parameter is invariant in type T.[error] You may wish to define T as +T instead. (SLS 4.5)[error]   val pr3  = ParameterRange( p3, 0, 10, 1 )[error]                              ^How can I ensure that the invariance is maintained? I take it this is a problem due to the use of the existential variable in ParameterRange (seems to be a common issue). Any suggestions?TIA,Hugo -- 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.
Open this post in threaded view
|

## Re: What constraints to add to ensure invariance - compiler infers Any instead of String

 The error is a bit confusing, but you are supposed to get an error, no?You pass in a Parameter[String] which sets the constraint T >: String, but then where a T is expected you pass in an Int, which sets T >: Int. To satisfy both constraints there is only one solution: T = Any. But Parameter is indeed invariant in T so Parameter[String] is not a subtype of Parameter[Any], hence the error.The error is proof that invariance is indeed ensured.Op dinsdag 31 januari 2017 16:41:56 UTC+1 schreef Hugo Ferreira:Hello,I have the following very basic code:  trait Parameter[ T ] {    type Self <: Parameter[ T ]    def apply( v: T ): Self  }  import scala.language.higherKinds  case class ParameterRange[ P[ X ] <: Parameter[ X ], T, U ](      val param: P[ T ],      val start: T,      val stop: T,      val config: U ){    def toStream( f: ( T, T, U ) => Stream[ T ] ): Stream[ P[ T ]#Self ] = {      val st = f( start, stop, config )      val r = st.map{ x: T => param( x ) }      r    }  }If I use an Int as the Parameter type I have no problems:  case class Param1( v: Int ) extends Parameter[ Int ] { type Self = Param1; def apply( v: Int ) = new Param1( v ) }  val p1 = Param1( 0 )  val pr1 = ParameterRange( p1, 0, 10, 1 )  val p2 = Param1( 1 )  val pr2 = ParameterRange( p2, 0, 10, 1 )But if I use a string:  case class Param3( v: String ) extends Parameter[ String ] { type Self = Param3; def apply( v: String ) = new Param3( v ) }  val p3 : Parameter[String] = Param3( "" )  val pr3  = ParameterRange( p3, 0, 10, 1 )I get an error:[error]  found   : NonConformanceToType.Parameter[String][error]  required: NonConformanceToType.Parameter[Any][error] Note: String <: Any, but trait Parameter is invariant in type T.[error] You may wish to define T as +T instead. (SLS 4.5)[error]   val pr3  = ParameterRange( p3, 0, 10, 1 )[error]                              ^How can I ensure that the invariance is maintained? I take it this is a problem due to the use of the existential variable in ParameterRange (seems to be a common issue). Any suggestions?TIA,Hugo -- 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.
Open this post in threaded view
|

## Re: What constraints to add to ensure invariance - compiler infers Any instead of String

 Appreciate the help Jasper.On Tuesday, 31 January 2017 16:04:01 UTC, Jasper-M wrote:The error is a bit confusing, but you are supposed to get an error, no?I would have though not.  You pass in a Parameter[String] which sets the constraint T >: String, but then where a T is expected you pass in an Int, which sets T >: Int. To satisfy both constraints there is only one solution: T = Any. But Parameter is indeed invariant in T so Parameter[String] is not a subtype of Parameter[Any], hence the error.The explanation makes sense and shows a fundamental flaw in my understanding of the typing. I create two Parameter, one for Int and another for String. When I create a  ParameterRange and pass on a Parameter of Int, I assume that it is independent of another object ParameterRangewere I place the String.  I am therefore expecting two  ParameterRange:ParameterRange[Parameter[Int], Int, Int]ParameterRange[Parameter[String], String, Int] The error is proof that invariance is indeed ensured.If the type T is shared between ParameterRanges,  yes. But aren't they two different objects with there own types and constraints? TIA,Hugo Op dinsdag 31 januari 2017 16:41:56 UTC+1 schreef Hugo Ferreira:Hello,I have the following very basic code:  trait Parameter[ T ] {    type Self <: Parameter[ T ]    def apply( v: T ): Self  }  import scala.language.higherKinds  case class ParameterRange[ P[ X ] <: Parameter[ X ], T, U ](      val param: P[ T ],      val start: T,      val stop: T,      val config: U ){    def toStream( f: ( T, T, U ) => Stream[ T ] ): Stream[ P[ T ]#Self ] = {      val st = f( start, stop, config )      val r = st.map{ x: T => param( x ) }      r    }  }If I use an Int as the Parameter type I have no problems:  case class Param1( v: Int ) extends Parameter[ Int ] { type Self = Param1; def apply( v: Int ) = new Param1( v ) }  val p1 = Param1( 0 )  val pr1 = ParameterRange( p1, 0, 10, 1 )  val p2 = Param1( 1 )  val pr2 = ParameterRange( p2, 0, 10, 1 )But if I use a string:  case class Param3( v: String ) extends Parameter[ String ] { type Self = Param3; def apply( v: String ) = new Param3( v ) }  val p3 : Parameter[String] = Param3( "" )  val pr3  = ParameterRange( p3, 0, 10, 1 )I get an error:[error]  found   : NonConformanceToType.Parameter[String][error]  required: NonConformanceToType.Parameter[Any][error] Note: String <: Any, but trait Parameter is invariant in type T.[error] You may wish to define T as +T instead. (SLS 4.5)[error]   val pr3  = ParameterRange( p3, 0, 10, 1 )[error]                              ^How can I ensure that the invariance is maintained? I take it this is a problem due to the use of the existential variable in ParameterRange (seems to be a common issue). Any suggestions?TIA,Hugo -- 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.
Open this post in threaded view
|

## Re: What constraints to add to ensure invariance - compiler infers Any instead of String

 Ok. I understand now. On Tuesday, 31 January 2017 16:26:39 UTC, Hugo Ferreira wrote:Appreciate the help Jasper.On Tuesday, 31 January 2017 16:04:01 UTC, Jasper-M wrote:The error is a bit confusing, but you are supposed to get an error, no?I would have though not.  You pass in a Parameter[String] which sets the constraint T >: String, but then where a T is expected you pass in an Int, which sets T >: Int. To satisfy both constraints there is only one solution: T = Any. But Parameter is indeed invariant in T so Parameter[String] is not a subtype of Parameter[Any], hence the error.The explanation makes sense and shows a fundamental flaw in my understanding of the typing. I create two Parameter, one for Int and another for String. When I create a  ParameterRange and pass on a Parameter of Int, I assume that it is independent of another object ParameterRangewere I place the String.  I am therefore expecting two  ParameterRange:ParameterRange[Parameter[Int], Int, Int]ParameterRange[Parameter[String], String, Int] The error is proof that invariance is indeed ensured.If the type T is shared between ParameterRanges,  yes. But aren't they two different objects with there own types and constraints? TIA,Hugo Op dinsdag 31 januari 2017 16:41:56 UTC+1 schreef Hugo Ferreira:Hello,I have the following very basic code:  trait Parameter[ T ] {    type Self <: Parameter[ T ]    def apply( v: T ): Self  }  import scala.language.higherKinds  case class ParameterRange[ P[ X ] <: Parameter[ X ], T, U ](      val param: P[ T ],      val start: T,      val stop: T,      val config: U ){    def toStream( f: ( T, T, U ) => Stream[ T ] ): Stream[ P[ T ]#Self ] = {      val st = f( start, stop, config )      val r = st.map{ x: T => param( x ) }      r    }  }If I use an Int as the Parameter type I have no problems:  case class Param1( v: Int ) extends Parameter[ Int ] { type Self = Param1; def apply( v: Int ) = new Param1( v ) }  val p1 = Param1( 0 )  val pr1 = ParameterRange( p1, 0, 10, 1 )  val p2 = Param1( 1 )  val pr2 = ParameterRange( p2, 0, 10, 1 )But if I use a string:  case class Param3( v: String ) extends Parameter[ String ] { type Self = Param3; def apply( v: String ) = new Param3( v ) }  val p3 : Parameter[String] = Param3( "" )  val pr3  = ParameterRange( p3, 0, 10, 1 )I get an error:[error]  found   : NonConformanceToType.Parameter[String][error]  required: NonConformanceToType.Parameter[Any][error] Note: String <: Any, but trait Parameter is invariant in type T.[error] You may wish to define T as +T instead. (SLS 4.5)[error]   val pr3  = ParameterRange( p3, 0, 10, 1 )[error]                              ^How can I ensure that the invariance is maintained? I take it this is a problem due to the use of the existential variable in ParameterRange (seems to be a common issue). Any suggestions?TIA,Hugo -- 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.