Is there a class for types having a single unit value (not sure of the correct terminology here) i.e. types with some pre-defined value?
class Unit a where
unit :: a
instance Unit () where
unit = ()
instance Unit (Maybe a) where
unit = Nothing
...for all Monoids, MonadPlus, etc.
I suppose another name for the class might be Default
. This would have been useful twice recently now for me.
Probably unconvincing example:
extract :: (Unit r)=> Reader r a -> a
extract r = runReader r unit
Does this exist? Do others think it might be useful?
A Unit is a Tuple from JavaTuples library that deals with only 1 element. Since this Unit is a generic class, it can hold any type of value in it. public final class Unit<A> extends Tuple implements IValue0<A> Using with () method: The with () method is a function provided by the JavaTuples library, to instantiate the object with such values.
Once the creation of unit tests becomes cumbersome, it signals that the code might be overcomplicated too. But without unit tests objectively answering the question of whether your code works or not, all you have is your own assumption. With unit tests, you have concrete proof.
Unit testing ensures that all code meets quality standards before it’s deployed. This ensures a reliable engineering environment where quality is paramount. Over the course of the product development life cycle, unit testing saves time and money, and helps developers write better code, more efficiently.
A Unit is a Tuple from JavaTuples library that deals with only 1 element. Since this Unit is a generic class, it can hold any type of value in it. Since Unit is a Tuple, hence it also has all the characterstics of JavaTuples:
Yes, it would probably be useful. In fact, all of the slightly incompatible versions of it would be useful! Which is kinda the problem.
It's not clear what such a class would even mean, which makes it hard to actually use, because inevitably you'll hit types where there are multiple choices of a default value, and if it's not immediately clear which one the instance provides, you pretty much lose all benefit of having the class in the first place.
A few examples:
For Monoid
instances, you'd obviously expect the identity element to be the default. But now you're back to the problem of so many types having two or more sensible Monoid
instances. Is the default Integer
0 or 1? For Monoid
, the standard library uses newtype
wrappers, but those are clumsy and make it difficult to work with the wrapped types--with Monoid
it works okay because you get access to mconcat
and such, but you can't do anything interesting with just a default value.
For Functor
-like types with an "empty" value, that gives an obvious default. This is what MonadPlus
and Alternative
are doing... and also overlaps with Monoid
, and if memory serves me there's at least one type where those three instances aren't identical. Which do you pick, when there's more than one choice? Consider lists: You can blindly append them, giving an arbitrary Monoid
, with the empty list as identity; but for lists of Monoids
you can also zipWith mappend
, giving a lifted monoid with repeat mempty
as the identity. Many functors have analogous Monoid
instances, but not always both--so whichever you pick for lists, you'll be conceptually inconsistent with some other Functor
!
For unit types like ()
, it's not hard to pick a default! But what about enumerations? Does it make sense to pick the first constructor? Sometimes, but not always. How will people using the class know?
What about Bounded
? If none of the above applies, you could use minBound
. But some of the above types could be Bounded
as well, so you'll confuse matters if their default isn't their minimum value.
Basically, there's just enough overlap that it seems to make sense... but really, you've got at least three different type classes in mind here, and trying to unify them is probably not as helpful as it seems at first.
If you can pin things down a little better and give a clear, consistent semantic interpretation of a "default" value, without just reinventing Monoid
or another existing class, such that the type class is easy to use without having to stop and think about what "default" gets chosen, great! But I wouldn't get my hopes up on making it work.
That said, the one obviously sensible case that's not covered by any standard type class is singletons like ()
. Most of the time these aren't terribly useful--for obvious reasons!--which is probably why there isn't such a class. One place where such a class is extremely useful, though, is when you're doing something involving type-level shenanigans, because such a type represents a single value at both the type and term level--so a class for such types lets you manipulate type-level values freely, then conjure up the term that goes with it, so you can pass it to some other function that might, e.g., select a type class instance based on it. For that reason, I have a class along those lines in my perpetually-incomplete type-hackery library, e.g.:
class TermProxy t where
term :: t
-- This makes explicit the lexical pun of () having type ().
instance TermProxy () where
term = ()
instance (TermProxy a, TermProxy b) => TermProxy (a, b) where
term = (term, term)
I doubt such a class is very useful in any other context, though.
You are looking for some sort of Default
type class. While the semantics of what a "default" should be is debatable (and I suggest you accept C.A. McCanns answer for his valuable comments there), you can get a Default
class from a fairly commonly used package called data-default
.
The class is:
-- | A class for types with a default value.
class Default a where
-- | The default value for this type.
def :: a
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With