snoyberg / classy-prelude

A typeclass-based Prelude.
108 stars 15 forks source link

Counterpart to `Semigroup` for empty elements? #77

Closed adnelson closed 9 years ago

adnelson commented 9 years ago

I like that Semigroup is split off into its own class. Similarly, though, I'd like to be able to generalize objects which might be empty (the other side of Monoid), without having to implement mappend. Is there a class for this in the ClassyPrelude?

gregwebs commented 9 years ago

It is in mono-traversable and exported by classy-prelude: http://hackage.haskell.org/package/mono-traversable-0.6.1/docs/Data-MinLen.html

Can you add some documentation to make it easier to find?

snoyberg commented 9 years ago

@gregwebs I think what @adnelson is looking for is:

class Empty a where
    empty :: a

which we haven't included anywhere since it has no clearly defined laws in the absence of some binary operation on it.

Note that we do have MonoPointed, which is essentially a generalization of singleton. While that function has historically had a similar criticism applied to it, I believe it does have meaningful laws in the context of MonoFoldable and Monoid, namely otoList . mconcat . map opoint == id.

Note that the Default value is bascially what you're looking for, but there's quite a bit of controversary around that class.

adnelson commented 9 years ago

Yeah, that's what I was asking. I'm not sure of the laws-side of things, but it does come in handy.

The Default class was another one that I was wondering about. I wasn't aware that it was controversial: it seems quite useful.

snoyberg commented 9 years ago

To give you an idea of the problem: what should be the Default (or Empty) instance for Int? Both 0 and 1 make sense, depending on if you're doing addition or multiplication. Without specifying that binary operator (via mappend), it's unclear what you mean, and therefore what you can reasonably do with def/empty.

gregwebs commented 9 years ago

at times I have one of this also however, this is not an issue for classy-prelude to solve. Classy-prelude enshrined modern best practices and tries to avoid requiring namespaces.

adnelson commented 9 years ago

I agree that in the case of Int or Bool or whatever, the default value is ambiguous. But for many others, that's not the case at all. For example, for types that represent configuration or options, a default value makes perfect sense (while appending probably makes no sense at all).

I agree that it might not be considered within the scope of classy-prelude, though.

gregwebs commented 9 years ago

It sounds like you want to use the default package. Personally I have found that just naming a default value defaultFoo is satisfying enough.