Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HMap.get does not support subtypes of keys #810

Open
ashleymercer opened this issue Jan 29, 2018 · 2 comments
Open

HMap.get does not support subtypes of keys #810

ashleymercer opened this issue Jan 29, 2018 · 2 comments

Comments

@ashleymercer
Copy link

ashleymercer commented Jan 29, 2018

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 ashleymercer changed the title HMap does not support subtyping HMap.get does not support subtypes of keys Jan 29, 2018
@ashleymercer
Copy link
Author

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 ~?>?

@elfprince13
Copy link

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] 	                                                                       ^

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

No branches or pull requests

3 participants