Skip to content
New issue

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

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

Already on GitHub? # to your account

#264 ❤️ #257 #267

Merged
merged 13 commits into from
Sep 19, 2021
Merged

#264 ❤️ #257 #267

merged 13 commits into from
Sep 19, 2021

Conversation

armanbilge
Copy link
Member

@armanbilge armanbilge commented Sep 3, 2021

Marries #264 and #257. Only remaining thing to consider is adding map and contramap to LookupKey and InsertKey.

cc @tpolecat

val in = g andThen outer.in
val out = outer.out andThen f
val in = AndThen(g) andThen outer.in
val out = AndThen(outer.out) andThen f
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neato, I didn't know about that one.

private[vault] type I
private[vault] def in: A => I

def contramap[B](f: B => A): InsertKey[B] =
Copy link
Member Author

@armanbilge armanbilge Sep 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that contramap and map will now be exposed on Key itself. It's safe, because you'll end up with an InsertKey/LookupKey after doing this, but it could be confusing.

@armanbilge
Copy link
Member Author

Cool, that wasn't bad at all. I think this is good to go.

@tpolecat
Copy link
Member

tpolecat commented Sep 8, 2021

Are we waiting on typelevel/cats#3987 here? If not are there any other blockers?

@armanbilge
Copy link
Member Author

armanbilge commented Sep 8, 2021

We're not. Actually, I didn't (want to) use any coyoneda here since that would mean adding a new dependency to cats-free, unless that's okay? So, no blockers.

Copy link
Member

@rossabaker rossabaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is good. Some of the overloads are making me fidgety, but I can be convinced.

@@ -11,3 +11,6 @@ tags
.vscode
.bsp
.jekyll-cache/

# metals
metals.sbt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 I can't remember who I've told, but ~/.config/git/ignore takes care of this on all your repos.

Comment on lines 61 to 66
def lock[A](k: InsertKey[A], a: A): Locker = new Locker(k.unique, k.in(a))

/**
* Put a single value into a Locker
*/
def lock[A](k: Key[A], a: A): Locker = lock(k: InsertKey[A], a)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overloads make me queasy and overloads where one is a subtype of another make me queasier still. I guess this is necessary for bincompat? Is there a different name we could give the InsertKey version?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or could we have just made this private[vault]?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have the same basic issue with unlock.

Copy link
Member Author

@armanbilge armanbilge Sep 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed for bincompat, and no private[vault] does not work because it disappears the static forwarders. I ran into this same issue in typelevel/fs2#2466 (comment).

OTOH, there is precedence for not caring about static forwarders in http4s/http4s#5071 (comment).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that was a good precedent. And it seems we're stuck with the overload on delete anyway. I find it a little confusing, but I don't see a good way out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe an unpopular opinion, one way out would be to deprecate the vault companion object based methods (I always found the duplication confusing, does anyone actually use them like this?) in favor of just calling these methods directly on the vault instance, and then just not add these new methods to the companion object.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't realize they existed on the companions. I think that's a good idea. The only weird one then is the overloaded Lock.lock, right? And perhaps the new one could be called apply?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, let me give that a try 👍

Comment on lines 63 to 71
/**
* Delete a key from the vault
*/
def delete[A](k: InsertKey[A]): Vault = Vault.delete(k, this)

/**
* Delete a key from the vault
*/
def delete[A](k: LookupKey[A]): Vault = Vault.delete(k, this)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, what happens if we call this with Key? Does it pick one from the linearization of Key? It doesn't really matter, I guess?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we call this with Key it uses the existing overload for Key and ignores both of these.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I overlooked that there's still a delete(Key[A]).

@armanbilge
Copy link
Member Author

@rossabaker the spec on overload resolution is here: https://www.scala-lang.org/files/archive/spec/2.13/06-expressions.html#overloading-resolution

tl;dr: overloaded methods are resolved to the most specific available for the given type. This is why if there are overloads for both InsertKey and LookupKey we must also provide an overload for Key to resolve the ambiguity.

rossabaker
rossabaker previously approved these changes Sep 18, 2021
@rossabaker rossabaker dismissed their stale review September 18, 2021 21:44

Arman had a better idea

@armanbilge
Copy link
Member Author

armanbilge commented Sep 18, 2021

@rossabaker I just pushed a commit that:

  1. Bumps base version to 3.1 (not strictly necessary since everything is source-compatible, but we are making a lot of changes?).
  2. Deprecates the companion object methods in favour of equivalent instance methods.
  3. Avoids the delete overloads by introducing one more abstraction DeleteKey that is the parent of all keys.

Copy link
Member

@rossabaker rossabaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 if green

@armanbilge
Copy link
Member Author

Good to go.

@rossabaker
Copy link
Member

I'll leave Chris and Rob a short window to object, but I'd like to release it this weekend and unblock Rob's PR for an http4s release train on Monday.

@rossabaker rossabaker requested a review from danicheg September 18, 2021 22:59
@rossabaker
Copy link
Member

Daniel, would love your thoughts here, too, if you've got time.

I think it's good, but this is all a slight move away from Tried And True Direct Haskell Port, so I'm being extra careful with it.

@rossabaker
Copy link
Member

I'm going to release this. We have a long-blocked and important http4s PR on this.

@rossabaker rossabaker merged commit 8fcd3cd into typelevel:main Sep 19, 2021
Copy link
Member

@danicheg danicheg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for being late (vacation in full swing). I think that's great work! And personally see no evil in moving away from direct Haskell port 🙈

@rossabaker
Copy link
Member

Enjoy your break!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants