Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
574 views
in Technique[技术] by (71.8m points)

typeclass - In scala, how to make type class working for Aux pattern?

Here is a simple example:

  trait Base {

    type Out
    def v: Out
  }

  object Base {

    type Aux[T] = Base { type Out = T }

    class ForH() extends Base {

      type Out = HNil

      override def v: Out = HNil
    }

    object ForH extends ForH
  }

  class TypeClass[B]

  trait TypeClassLevel1 {

    def summon[B](b: B)(implicit ev: TypeClass[B]): TypeClass[B] = ev
  }

  object TypeClass extends TypeClassLevel1 {

    implicit def t1: TypeClass[Base.Aux[HNil]] = new TypeClass[Base.Aux[HNil]]

    implicit def t2: TypeClass[Int] = new TypeClass[Int]
  }

  it("No Aux") {

    val v = 2

    TypeClass.summon(v) // works
  }


  it("Aux") {

    val v = new Base.ForH()

    TypeClass.summon(v) // oops
    TypeClass.summon(Base.ForH) // oops

    val v2 = new Base.ForH(): Base.Aux[HNil]
    TypeClass.summon(v2) // works!
  }

The object Base/ForH clearly has a stable path, this eliminate the possibility of the compiler not being able to resolve type ForH.Out.

What bothers me is not how incapable the compiler is to figure out the fact that ForH <:< Aux[HNil], but how easy it is to patch it up, just by a simple type upcast (last 2 lines). IMHO both features (type lambda & type classes) are important aspect of functional programming, why they can't work together at the same time?

If you are familiar with the compiler design I'll have an extra question: what does it take to improve the type class search algorithm to make it happen? Thanks a lot for your opinion.

UPDATE 1: a specific fix has been proposed but I have another problem trying to generalise it, please see In scala, how to make type class working for Aux pattern? - Part 2 for detail

question from:https://stackoverflow.com/questions/65838535/in-scala-how-to-make-type-class-working-for-aux-pattern

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

So the compiler is able to infer ForH <:< Aux[HNil], but (tbh I don't know exactly why) when resolving an implicit when the return type uses a type lambda, it gets confused if you don't use a type bound.

Anyway that's probably not a great explanation, but at least I can make your code compile. Just change t1 to:

implicit def t1[T <: Base.Aux[HNil] ]: TypeClass[T] = new TypeClass[T]

this works for me in scastie using Scala 2.13.4.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...