Open satorg opened 4 days ago
I like the idea of these methods, but the proposed name seems a little ambiguous and uncertain. I'm more concerned about 'unique', which in the context of SQL seems fine, but outside of that scope, it could imply that the element is distinct in some way, rather than just that the collection contains exactly one element.
I think 'sole' might be a better choice here. So, what do you think about soleOrRaise
and soleOrEmptyOrRaise
? The latter feels clunky but at least echoes the former.
Another option here is to use 'ensure', which comes from the MonadError
scope: ensureSole
and ensureSoleOrEmpty
. These names contradict the typical presence of a boolean predicate in the contract of MonadError
methods, but we implicitly encode it in the naming with 'sole' and 'soleOrEmpty'.
I would be happy to merge a PR with these additions.
I agree with @danicheg's points re: naming. I like ensureSole and ensureSoleOrEmpty myself.
@danicheg , @benhutchison , thank you for your feedback!
Yes, I agree that we should choose better names – I picked those just to have something to start with.
Regarding the suggested ones. At first I favored the ensureSole*
options. But then it appeared to me that those names might not be fully idiomatic, because the original ensure
and ensureOr
combinators do not modify their inputs. But the combinators we're discussing are supposed to do that. So perhaps, the sole...OrRaise
names would be a better fit for them.
Btw, is the sole
word better in this context comparing to single
? Just wondering, because I usually see something like "single-ton" but not "sole-ton". Just out of curiosity though – I'm totally fine with the "sole" wording anyway.
Another thing that I feel it is important to think through.
Initially, I proposed the Foldable
typeclass to use for the sake of generalization, which would be able to do the job for sure.
However, there's another one in Cats – UnorderedFoldable
, which is a parent for Foldable
. For example, UnorderedFoldable
captures hash-based Sets. Therefore I feel that UnorderedFoldable
could be a better bet to rely upon for the proposed functionality. Unfortunately, UnorderedFoldable
looks a bit under-developed at the moment. It doesn't include methods that would allow to short-circuit calculations. For example, Foldable
has foldM
, etc, but there's nothing like that in UnorderedFoldable
. And I wouldn't like to be forced to go through all the items just to check whether there are more than one available.
Therefore I think that perhaps it would be beneficial to give it a shot and add the missing combinators to UnorderedFoldable
first, then come back to this task later once the missing functionality becomes enabled. Or do you think that Foldable
is already good enough for that?
Thank you!
@satorg It's clear youve given this a lot of thought. I'll back whichever choice you come to in terms of sole
/ single
, and ensure
/ ..OrRaise
.
Seems depending on UnorderedFoldable
would be ideal. If you have the patience and energy to extend that class with foldM, then circle back and add these operators, great! If not, and just go with Foldable, it's still a net gain in my view.
Inspired by Doobie's
unique
andoption
queries:https://github.com/typelevel/doobie/blob/1ad3ad5e195d89becbd4097677f738a0b10aa5df/modules/core/src/main/scala/doobie/util/query.scala#L127-L139
In fact, those two are pretty common use cases: after receiving a collection of items from somewhere, we may want to make sure that there's either exactly 1 or at most 1 items received.
To make them generally available, we could consider adding two combinators to
FNested2SyntaxOps
:The proposed names may not be perfect – just got borrowed them from Doobie. However, I'm absolutely open for bikeshedding.
If such combinators make sense, I'll be glad to file a PR.