Skip to content

Instantly share code, notes, and snippets.

@DmytroMitin
Last active December 13, 2020 16:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DmytroMitin/0ef4c93b9a58a1f2e1d92f71fbdbfb19 to your computer and use it in GitHub Desktop.
Save DmytroMitin/0ef4c93b9a58a1f2e1d92f71fbdbfb19 to your computer and use it in GitHub Desktop.
object App {
trait MyTrait
object MyTrait {
def materialize[A <: MyTrait](implicit m: A): A = m
}
implicit val m/*: MyTrait*/ /*: (MyTrait {
/*implicit*/ val x: Int
})*/ = new MyTrait {
implicit val x: Int = 10
}
val m1 = MyTrait.materialize
import m1._
implicitly[Int]
}
@BalmungSan
Copy link

BTW, just to propose a counter example this will work.

object App {
  trait MyTrait {
    type T
    implicit def t: T
  }
  object MyTrait {
    def materialize[A](implicit m: MyTrait { type T = A}): MyTrait { type T = A}= m
  }

  implicit val m: MyTrait { type T = Int } = new MyTrait {
    override type T = Int
    override implicit val t: T = 42
  }
  val m1 = MyTrait.materialize[Int]
  import m1._
  println(implicitly[Int]) // 42.
}

Better yet, use type parameters instead of type members, which aren't needed at all in this example.

-- Sincerely, Luis Miguel Mejía Suárez.

@DmytroMitin
Copy link
Author

@BalmungSan well, you changed the trait. This can be a third-party type class.

Usually with type classes type parameters are used as inputs and type members as outputs.

@DmytroMitin
Copy link
Author

DmytroMitin commented Apr 6, 2019

object App {
  class A
  class B
  class C
  class D

  trait MyTrait[A]
  object MyTrait {
    def materialize[A] = new Helper[A]

    class Helper[A] {
      def apply[MT <: MyTrait[A]](implicit mt: MT): MT = mt
    }

    implicit val intMT = new MyTrait[Int] {
      implicit val a: A = new A
      implicit val b: B = new B
    }

    implicit val stringMT = new MyTrait[String] {
      implicit val c: C = new C
      implicit val d: D = new D
    }
  }

  {
    val m = MyTrait.materialize[Int].apply
    import m._
    implicitly[A]
    implicitly[B]
  }

  {
    val m = MyTrait.materialize[String].apply
    import m._
    implicitly[C]
    implicitly[D]
  }

}

@DmytroMitin
Copy link
Author

import shapeless.{::, HList, HNil, Poly2}

object App {

  def swap(p: Poly2)/*: Poly2*/ /*: (Poly2 {
    /*implicit*/ def cse[L <: HList, A, B](implicit
                                       ev: L <:< (A :: B :: HNil),
                                       pCase: p.Case[B, A]
                                      ): ProductCase.Aux[L, pCase.Result]
  })*/ = new Poly2 {
    implicit def cse[L <: HList, A, B](implicit
                                       ev: L <:< (A :: B :: HNil),
                                       pCase: p.Case[B, A]
                                      ): ProductCase.Aux[L, pCase.Result] = ProductCase(l => {
      val a :: b :: HNil = ev(l)
      pCase(b, a)
    })
  }

  object myPoly extends Poly2 {
    implicit val intCase: Case.Aux[Int, Boolean, Long] = at((i, _) => i.toLong)
    implicit val strCase: Case.Aux[String, Char, Symbol] = at((s, c) => Symbol(s + c))
  }

  val myPoly1 = swap(myPoly)
  import myPoly1._
  myPoly1(true, 10)
  myPoly1('c', "ab")
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment