Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typeclass Containing Element in HList?

I'm trying to define a typeclass such that the HList, L, contains a specific type, A.

trait Contains[A] {
  type Out
}
object Contains {

  type Aux[A, O] = Contains[A] { type Out = O }

  def contains[L <: HList, A]
       (implicit ev: Contains.Aux[L, A]) = ev

  implicit def containsInt[H, L <: HList, A]
       (implicit ev: H == A): Contains.Aux[H :: L, A] =
    new Contains[H :: L] {
      type Out = A
    }
}

Of course it does not compile due to ev: H == A.

Does such an "equivalent type" typeclass exist?

Once it works, I'd expect the following to compile:

implicitly[Contains.Aux[Int :: HNil, Int]] since there's an Int in the HList.

Whereas, I would expect implicitly[Contains.Aux[String :: HNil, Boolean] to not compile since there's no Boolean in the input HList.

like image 467
Kevin Meredith Avatar asked Apr 01 '26 07:04

Kevin Meredith


1 Answers

You're looking for shapeless.ops.hlist.Selector.

With Selector your examples work out like this,

scala> import shapeless._, ops.hlist._
import shapeless._
import ops.hlist._

scala> Selector[Char :: HNil, Char]
res0: shapeless.ops.hlist.Selector[shapeless.::[Char,shapeless.HNil],Char] = shapeless.ops.hlist$Selector$$anon$37@20eebe9c

scala> Selector[Int :: Char :: HNil, Char]
res1: shapeless.ops.hlist.Selector[shapeless.::[Int,shapeless.::[Char,shapeless.HNil]],Char] = shapeless.ops.hlist$Selector$$anon$38@10cf3c87

scala> Selector[Int :: HNil, Int]
res2: shapeless.ops.hlist.Selector[shapeless.::[Int,shapeless.HNil],Int] = shapeless.ops.hlist$Selector$$anon$37@79d8c266

scala> Selector[Boolean :: Char :: HNil, Int]
<console>:18: error: Implicit not found: shapeless.Ops.Selector[shapeless.::[Boolean,shapeless.::[Char,shapeless.HNil]], Int]. You requested an element of type Int, but there is none in the HList shapeless.::[Boolean,shapeless.::[Char,shapeless.HNil]].
       Selector[Boolean :: Char :: HNil, Int]
               ^

scala> Selector[Boolean :: Char :: HNil, Char]
res4: shapeless.ops.hlist.Selector[shapeless.::[Boolean,shapeless.::[Char,shapeless.HNil]],Char] = shapeless.ops.hlist$Selector$$anon$38@bf88c94

scala> Selector[Boolean :: Int :: Char :: HNil, Char]
res5: shapeless.ops.hlist.Selector[shapeless.::[Boolean,shapeless.::[Int,shapeless.::[Char,shapeless.HNil]]],Char] = shapeless.ops.hlist$Selector$$anon$38@653f47f

scala> Selector[Int :: HNil, HNil]
<console>:18: error: Implicit not found: shapeless.Ops.Selector[shapeless.::[Int,shapeless.HNil], shapeless.HNil]. You requested an element of type shapeless.HNil, but there is none in the HList shapeless.::[Int,shapeless.HNil].
       Selector[Int :: HNil, HNil]
               ^
like image 63
Miles Sabin Avatar answered Apr 03 '26 22:04

Miles Sabin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!