Re: [scala-user] How to prioritize contravariant type classes?

79 views
Skip to first unread message

Luke Vilnis

unread,
Feb 21, 2013, 8:46:59 PM2/21/13
to Paul Phillips, scala-debate
So, understanding that introducing an additional concept of "specificity" to the language is unlikely to happen, I wonder if slightly better hacks to implicit resolution/prioritization could be added. One idea is that instead of computing a score between 0-2 to determine which implicit takes priority, could we just add a special annotation to the language that lets us bump up/down the score of an implicit? So instead of having a default contravariant implicit and being out of luck because of the (+1 is subtype, -1 appears in supertype) adjustment, we could just add an annotation "@priority(-1)" and break the tie. Is this something that has been proposed before?

On Thu, Feb 21, 2013 at 2:48 PM, Paul Phillips <pa...@improving.org> wrote:
[I'm not on scala-user.]

On Thu, Feb 21, 2013 at 10:56 AM, Luke Vilnis <lvi...@gmail.com> wrote:
And of course when I call implicitly[SerializerMaker[B]], I get an ambiguity error between the two implicits since sa is more specific, but sb is in the subclass. Is there any way to override sa? Or any kind of black magic/hax that I can use to get the kind of behavior I'm looking for?

See "end the blight of contrarivariance."


It's a very old issue and the only obstacle to fixing it is convincing martin that you'd rather have a SerializerMaker[B] than a SerializerMaker[A], even if SerializerMaker is contravariant.


Paul Phillips

unread,
Feb 21, 2013, 10:26:48 PM2/21/13
to Luke Vilnis, scala-debate

On Thu, Feb 21, 2013 at 5:46 PM, Luke Vilnis <lvi...@gmail.com> wrote:
Is this something that has been proposed before?

Proposed and implemented. The second commit is the elimination of all the LowPriority* traits which the annotation enabled.

https://github.com/paulp/scala/commit/c01e44786
https://github.com/paulp/scala/commit/8fc46cabe7

Alois Cochard

unread,
Feb 22, 2013, 5:29:44 AM2/22/13
to scala-...@googlegroups.com, Luke Vilnis
Hey this is really cool!

I'll probably be able to solve my CBF overriding issue with this :)

Thanks

Paul Phillips

unread,
Feb 22, 2013, 9:58:46 AM2/22/13
to Alois Cochard, scala-...@googlegroups.com, Luke Vilnis

On Fri, Feb 22, 2013 at 2:29 AM, Alois Cochard <alois....@gmail.com> wrote:
I'll probably be able to solve my CBF overriding issue with this :)

Probably not, unless you are interested in managing a fork of scala.

Alois Cochard

unread,
Feb 22, 2013, 12:55:46 PM2/22/13
to scala-...@googlegroups.com, Alois Cochard, Luke Vilnis
Oh sh... I missed it was in your fork.

No problem, I'll deploy "scapaul" in production ;)

Luke Vilnis

unread,
Feb 22, 2013, 2:11:17 PM2/22/13
to Alois Cochard, scala-...@googlegroups.com
As always, eagerly awaiting Paul's Scala fork... "Paula"? 

Anyhow, I figured out a pretty crazy semi-workaround for this problem - it allows compile time checking that there is _some_ compatible serializer available, but still to use the most specific one. Basically, I still use the contravariant type class as compile-time evidence that some serializer exists, but I find the most specific one by picking the first match in a list:

class CubbieMaker[-C](make: C => Cubbie)(implicit m1: Manifest[C]) {
  CubbieMaker.makers += this
  def tryMake[T](toConvert: T)(implicit m2: Manifest[T]): Option[Cubbie] =
    if (m2 <:< m1) Some(make(toConvert.asInstanceOf[C])) else None
}

object CubbieMaker {
  val makers = new mutable.ArrayBuffer[CubbieMaker[_]]
  // just define overriding CubbieMakers here earlier than the less specific versions and they will be found earlier in search through the "makers" list
  implicit val modm = new CubbieMaker[Model](new ModelCubbie(_))
  implicit val cdm = new CubbieMaker[CategoricalDomain[String]](new CategoricalDomainCubbie(_))
  implicit val smm = new CubbieMaker[mutable.HashMap[String, String]](new StringMapCubbie(_))
  implicit val csdm = new CubbieMaker[CategoricalSeqDomain[String]](new CategoricalSeqDomainCubbie(_))
  implicit val cdtdm = new CubbieMaker[CategoricalDimensionTensorDomain[String]](new CategoricalDimensionTensorDomainCubbie(_))

  def cubbieForType[T](toSerialize: T)(implicit m: Manifest[T], evidenceThatWeHaveCubbieMaker: CubbieMaker[T]): Cubbie =
    makers.foldLeft(None: Option[Cubbie])((resOpt, maker) => if (resOpt.isDefined) resOpt else maker.tryMake(toSerialize)).get

Jan Vanek

unread,
Feb 22, 2013, 2:46:45 PM2/22/13
to scala-...@googlegroups.com
On 22.02.2013 20:11, Luke Vilnis wrote:
As always, eagerly awaiting Paul's Scala fork... "Paula"?

Scalpel.

--
You received this message because you are subscribed to the Google Groups "scala-debate" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-debate...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Ben Hutchison

unread,
Feb 25, 2013, 7:48:05 AM2/25/13
to Luke Vilnis, Paul Phillips, scala-debate
On Thu, Feb 21, 2013 at 2:48 PM, Paul Phillips <pa...@improving.org> wrote:
See "end the blight of contrarivariance."


It's a very old issue and the only obstacle to fixing it is convincing martin that you'd rather have a SerializerMaker[B] than a SerializerMaker[A], even if SerializerMaker is contravariant.


FWIW, agree. I really don't like this oddity of how contravariant type classes currently behave. Like others, it seems, I find present behavior obstructs the use of type classes in the natural way one wants to apply them. My vote is for change on this aspect of Scala; it'd be a move to a better place.

Also, I've never clearly understood what the downside to this change would be.. is it something more theoretical/ideological? or is it more concerns about the cost & impact of a significant breaking change to the language spec?

-Ben

John Nilsson

unread,
Feb 25, 2013, 3:04:39 PM2/25/13
to Ben Hutchison, Luke Vilnis, Paul Phillips, scala-debate
Don't forget this thread. It actually looked promising! :)

https://groups.google.com/d/msg/scala-debate/QTo_n3U9B0k/yP-canA9qCAJ

BR,
John


--
Reply all
Reply to author
Forward
0 new messages