shapeless icon indicating copy to clipboard operation
shapeless copied to clipboard

HMap.get does not support subtypes of keys

Open ashleymercer opened this issue 7 years ago • 2 comments

Regular Map.get allows using subtypes:

val v = Map(Option("foo") -> "bar", Option(23) -> 13)
val b = v.get(Some("foo"))  // "bar"

but the same isn't true of HMap, because it can't resolve the implicits necessary to prove that the value type is correct:

val v = HMap[(Option ~?> Id)#λ](Option("foo") -> "bar", Option(23) -> 13)
val b = v.get(Some("foo"))

// [error] could not find implicit value for parameter ev: Option ~?> shapeless.Id#λ[Some[String],V]
// [error] val b = v.get(Some("foo"))
// [error]                      ^

Would it be possible / sensible to make ~?>.λ variant in K, or would that cause other problems?

ashleymercer avatar Jan 29 '18 16:01 ashleymercer

I've had a bit more of a play around, and providing this implicit seems to allow subclassing to work as expected:

implicit def idValueWitnessSubclass[K[_], K1[_] <: K[_], T](implicit rel: K ~?> Id): (K ~?> Id)#λ[K1[T], Id[T]] = new rel.λ

Would it be worth adding this (and idKeyWitnessSubclass) to object ~?>?

ashleymercer avatar Jan 29 '18 17:01 ashleymercer

Not sure if anyone is still watching this, but I've run into a similar issue.

The documentation is pretty ~~dense~~ nonexistent, but I have the following, based on the lone HMap example:

class FieldMap[Op <: OpBase[Op, Node], Node <: NodeBase[Op, Node], UpdaterT <: AtomicFieldUpdater[Node, FieldT], FieldT]

implicit def updaterToCacheValue[Op <: OpBase[Op, Node], Node <: NodeBase[Op, Node], UpdaterT <: AtomicFieldUpdater[Node, FieldT], FieldT]:FieldMap[Op,Node,UpdaterT,FieldT] = new FieldMap[Op,Node,UpdaterT,FieldT]

type FieldHMap[Op <: OpBase[Op, NodeT], Node <: NodeBase[Op, Node]] = HMap[Lambda[(`UpdaterT <: AtomicFieldUpdater[Node, FieldT]`, FieldT) => FieldMap[Op, Node, UpdaterT, FieldT]]]

(Lambda comes from https://github.com/non/kind-projector, I assume there's something similar built-in to shapeless, but again, the documentation is rough).

The error message I get is:

[error] /full/path/redacted.scala:39: kinds of the type arguments ([UpdaterT <: edu.brown.lockfree.AtomicFieldUpdater[Node,FieldT], FieldT]edu.brown.lockfree.FieldMap[Op,Node,UpdaterT,FieldT]) do not conform to the expected kinds of the type parameters (type R) in class HMap.
[error] [UpdaterT <: edu.brown.lockfree.AtomicFieldUpdater[Node,FieldT], FieldT]edu.brown.lockfree.FieldMap[Op,Node,UpdaterT,FieldT]'s type parameters do not match type R's expected parameters:
[error] type UpdaterT's bounds <: edu.brown.lockfree.AtomicFieldUpdater[Node,FieldT] are stricter than type _'s declared bounds >: Nothing <: Any
[error] 	type FieldHMap[Op <: OpBase[Op, Node], Node <: NodeBase[Op, Node]] = HMap[Lambda[(`UpdaterT <: AtomicFieldUpdater[Node, FieldT]`, FieldT) => FieldMap[Op, Node, UpdaterT, FieldT]]]
[error] 	                                                                       ^

elfprince13 avatar Aug 01 '18 21:08 elfprince13