As explained in the link you pointed out, such an operation is only possible on HList if your values ββare statically entered as Some and None , so the compiler can do something about it.
If you have additional information about what the type gives (here the fact that exactly one of the parameters may be Some ), this means that you are using the wrong type, since types are the information that you have about the values ββduring compilation. In this case, the type you should use is Coproduct :
type AnimalCoproduct = Cat :+: Dog :+: Fish :+: CNil val dog = Coproduct[AnimalCoproduct](Dog("brown"))
Now back to your question, assuming that you know what is None and which are Some at compile time.
First you need to check which HList has the property that they are a None list.
trait IsNoneList[L <: HList] object IsNoneList {
So, if there is implicit IsNoneList[L] , this means that L is HList of None.type . Let me do the same with the property we are looking for:
trait IsOneSomeHList[L <: HList] { type OneSome def get(l: L): OneSome } object IsOneSomeHList { type Aux[L <: HList, O] = IsOneSomeHList[L] { type OneSome = O } def apply[L <: HList](implicit L: IsOneSomeHList[L]) = L // if the tail is full of None, and the head is a Some, then the property is true implicit def someHead[A, T <: HList: IsNoneList]: Aux[Some[A] :: T, A] = new IsOneSomeHList[Some[A] :: T] { type OneSome = A def get(l: Some[A] :: T) = l.head.get } //if the head is None, and the tail has the property, then the HCons also has the property, with the same extraction function implicit def noneHead[T <: HList](implicit T: IsOneSomeHList[T]): Aux[None.type :: T, T.OneSome] = new IsOneSomeHList[None.type :: T] { type OneSome = T.OneSome override def get(l: ::[None.type, T]): T.OneSome = T.get(l.tail) } }
Note that if we have implicit IsOneSomeHList[L] in scope, we know that L has the property we want, but we can also use this implicit to get the type and value of the only Some in the list.
EDIT
Here is an example:
val cat = Some(Cat(isFriendly = true)) :: None :: None :: HNil IsOneSomeHList[Some[Cat] :: None.type :: None.type :: HNil].get(cat) == Cat(true)