Where is the Monoid instance on Comparison defined? - haskell

newtype Comparison a is defined in Data.Functor.Contravariant.
In the version of this module defined in contravariant-1.5, the Monoid instance on Contravariant is defined as follows:
instance Monoid (Comparison a) where
mempty = Comparison (\_ _ -> EQ)
mappend (Comparison p) (Comparison q) = Comparison $ mappend p q
Data.Functor.Contravariant is also defined in base (as of GHC 8.6.1, apparently).
In base, the Monoid instance on Comparison is defined as follows:
deriving instance Semigroup (Comparison a)
deriving instance Monoid (Comparison a)
What enables the instance for Monoid (Comparison a) to be automatically derived in base?
And where should I look to see the definitions of mempty and mappend for it?

For newtypes, with GeneralizedNewtypeDeriving enabled, the instance is obtained using the instance of the underlying type.
So, mempty # a -> a -> Ordering is used (ditto for mappend), and then rewrapped as mappend :: Comparison a.
Note that this ultimately involves the semigroup/monoid instances for function types b -> c and the ones for Ordering.

The Comparison type is just a newtype over a -> a -> Ordering.
Ordering is a Semigroup instance defined in, I think, GHC.Base.
Another relevant instance of Semigroup is:
Semigroup b => Semigroup (a -> b)
That is, any function type a -> b has a Semigroup instance if b has a Semigroup instance.
You can think of a -> a -> Ordering as a -> (a -> Ordering), i.e. a function that takes a as input, and returns (a -> Ordering) as output. Since (a -> Ordering) is a Semigroup instance, then a -> (a -> Ordering) is, too.
The same line of reasoning applies to Monoid.
Finally, as chi wrote in another answer, GeneralizedNewtypeDeriving takes care of the rest.

Related

For what Alt in Monoid instance needed?

In Monoid and Semigroup instances of Alternative Alt used.
Why we can't write instance without it?
{-# LANGUAGE FlexibleInstances #-}
instance Alternative f => Semigroup (f a) where
(<>) = <|>
instance Alternative f => Monoid (f a) where
mempty = empty
And if we can write that, can we then replace Alternative with (Monoid (f a), Applicative f) in functions?
You use it for deriving Monoid for any Alternative
{-# Language DerivingVia #-}
data F a = ..
deriving (Semigroup, Monoid)
via Alt F a
instance Functor F where ..
instance Applicative F where ..
instance Alternative F where ..
Alt is a newtype for good reason as there are many ways to describe Monoid behaviour for an applied type f a. For example Applicative lifting: Ap.
{-# Language DerivingVia #-}
data G a = ..
deriving (Semigroup, Monoid, Num, Bounded)
via Ap G a
instance Functor G where ..
instance Applicative G where ..
The instances you give are maximally overlapping, the Monoid instance of any applied type is now forced to be the Alternative instance, completely ignoring the a parameter.
There are many instances where this would not be correct, for example Semigroup a => Semigroup (Maybe a) is not the same as the Semigroup you would get from Alternative Maybe.
It is possible using a rather new feature QuantifiedConstraints to quantify over the argument of a type constructor forall x. Monoid (f x). This is not the same as Alternative but similar
{-# Language QuantifiedConstraints #-}
..
type Alternative' :: (Type -> Type) -> Constraint
class (forall x. Monoid (f x)) => Alternative' f
instance (forall x. Monoid (f x)) => Alternative' f
You use the (<|>) :: Alternative f => f a -> f a -> f a and empty :: Alternative f => f a. As the signatures suggest, these are defined for items of type Applicative f => f a. You thus can only use these functions to process such items, and this thus requires that if you work with an f a, for eample to define mempty :: f a with mempty = empty, then that requires that f is a member of the Alternative typeclass.
That being said, while a lot data types can have a Semigroup and Monoid instance defined as how the Alternative is implemented, this is not per se the best instance. Yes Alternative is a monoid on applicative functors, but that should not per se be the monoid instance on these data types.
If the instances you propose existed in that form, every type that matches f a would immediately defer to it. That includes types where it makes sense, but consider
newtype ResultsSum a = ResultsSum {funToSum :: a -> Int}
instance Semigroup (ResultsSum a) where
ResultsSum p <> ResultsSum q = ResultsSum $ \x -> p x + q x
Unfortunately though, ResultsSum a matches f a. But it is not an Alternative; it isn't even a functor, and can't be (rather, it is Contravariant). However, the compiler doesn't take that into account when resolving instances: it just sees two instance declarations whose heads both purport to enable ResultsSum being a semigroup, which triggers an ambiguous-instance error.
Granted, this example could be addressed with {-# OVERLAPPING #-} pragmas, but it's always best to avoid instance overlaps as they can lead to strange. It's unnecessary, since you can also also derive those instances via the Alternative one. Though I personally would actually rather do it the other way around: define the Monoid instance first and then Alternative in terms of it.

Quantified Constraints for Higher-kinded Typeclasses

Suppose I would like to write two Typeclasses.
Header:
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE UndecidableInstances #-}
import Data.Complex
The first typeclass ExClass was defined as such:
class (forall a. (Monoid (t a))) => ExClass t where
exFunc :: [t (Complex a)] -> t (Complex a)
exFunc = mconcat -- the actual function is more complicated
exFunc2 :: (RealFloat a) => t (Complex a) -> a
I defined it as a higher-kinded typeclass because one of its functions' output type depends on the type of its nested value a. I would also like to have a default implementation for exFunc, but it involves the assumption that t a is a Monoid. Now I would like to write an instance for the following type:
newtype ExType a = ExType a
ExType a is a Monoid only when Num a is true:
instance (Num a) => Semigroup (ExType a) where
ExType a <> ExType b = ExType (a * b)
instance (Num a) => Monoid (ExType a) where
mempty = ExType 1
Now I go on to define the typeclass instance for ExClass, specifying the constraint of Num a:
instance (forall a. Num a) => ExClass ExType where
exFunc2 (ExType a) = magnitude a
The above code will compile with no problem. However, if I were to try to use the implemented function like so:
x = ExType 2 :: ExType (Complex Double)
func = exFunc2 x
I receive the following complaint:
• No instance for (Num a) arising from a use of ‘exFunc2’
Possible fix: add (Num a) to the context of a quantified context
• In the expression: exFunc2 x
In an equation for ‘func’: func = exFunc2 x
This also happens when I use a different instance declaration:
instance (forall a. Monoid(ExType a)) => ExClass ExType where
exFunc2 (ExType a) = magnitude a
Is there a way to make this typeclass work? or am I just not supposed to structure my program like this at all?
Daniel Wagner has already explained in his answer the problems with the current definition.
It seems that you want ExClass to mean something like "a class of container types that have a special relationship with another class c applied to their elements, and when their elements satisfy c, the containers themselves are monoids".
For example: ExType has a special relationship with Num. When the elements a of ExType satisfy Num, ExType a becomes a Monoid.
(This is already affirmed in ExTypes Monoid instance, but it seems you want to express it with a higher level of abstraction; to have a class for those containers that become monoids in a similar way.)
In Haskell, there are various possible ways to express a relationship between two types—or between a type and a Constraint. Let's use MultiParameterTypeClasses:
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ConstraintKinds #-}
import Data.Kind (Type, Constraint)
-- This kind signature is not strictly required, but makes things clearer
type ExClass :: (Type -> Constraint) -> (Type -> Type) -> Constraint
class (forall a . c a => Monoid (t a)) => ExClass c t | t -> c where
exFunc :: c a => [t a] -> t a
exFunc = mconcat
Notice that ExClass has now two parameters, and that the type f of the container determines (through a functional dependency) the constraint c that is required of the elements of f for f to be a Monoid. c might be different for different fs!
The Semigroup and Monoid instances for ExType don't change. The ExClass instance for ExType would now be:
instance ExClass Num ExType where
exFunc = mconcat
Putting it to work:
main :: IO ()
main = print $ exFunc [ExType (1::Int), ExType 2]
(I have left out the Complex datatype, which might throw another wrench in the definition.)
I think there's a couple reasoning errors going on here at once.
First: when you write
class (forall a. Monoid (t a)) => ExClass t
this means that if somebody wants to implement an ExClass t instance, then they must show that there is an instance of the form instance Monoid (t a) where ... with no constraints whatsoever on a. Note also that it is not enough for there to be instances for all possible choices of a -- the instance itself must be parametric.
Second: when you write
instance (forall a. Num a) => ExClass ExType
there is no magical connection between the a mentioned here and the a mentioned in the definition of ExClass.
Third: when you write
instance (forall a. Num a) => ExClass ExType
this doesn't actually make an instance of ExClass ExType yet. It makes an instance conditioned on a proof that forall a. Num a. In general, the meaning of instance Ctx => C t is that anybody who wants to assume the fact C t must be able to themselves prove Ctx. Nobody's going to reasonably be able to show forall a. Num a, so this instance is unusable.
These last two comments apply essentially unchanged to your second attempt,
instance (forall a. Monoid(ExType a)) => ExClass ExType
Unfortunately, without more details on what you're trying to do and why, it's nigh-on impossible to suggest the right route forward. Possibilities include an indexed-monad-like approach, moving the class constraint from the class context to various method contexts, not making a class at all, and more.
I would also like to have a default implementation for exFunc, but it involves the assumption that t a is a Monoid
You only require Monoid (t a) in order to have a default implementation? That's backwards. If that constraint isn't conceptually required as a superconstraint for ExClass, then it shouldn't be in the class head.
You can still have a default implementation that is more restrictive:
{-# LANGUAGE DefaultSignatures #-}
class ExClass t where
exFunc :: [t (Complex a)] -> t (Complex a)
default exFunc :: Monoid (t (Complex a)) => [t (Complex a)] -> t (Complex a)
exFunc = mconcat
exFunc = mconcat -- the actual function is more complicated
exFunc2 :: (RealFloat a) => t (Complex a) -> a
And then simply
instance ExClass ExType where
exFunc2 (ExType a) = magnitude a
You would still also be able to provide instances that don't fulfill the Monoid constraint at all, you just then would need to manually implement exFunc too.
Even simpler is to not bother with default implementations at all, but just provide a helper that can be used to get a simple implementation without duplicating any code:
class ExClass t where
exFunc :: [t (Complex a)] -> t (Complex a)
exFunc = mconcat -- the actual function is more complicated
exFunc2 :: (RealFloat a) => t (Complex a) -> a
monoidIshExFunc :: Monoid (t (Complex a)) => [t (Complex a)] -> t (Complex a)
monoidIshExFunc = mconcat
instance ExClass ExType where
exFunc = monoidIshExFunc
exFunc2 (ExType a) = magnitude a
(monoidIshExFunc could even require ExClass t, just obviously you should be careful to not end up in a circular definition!)

What are FromJSON1 and ToJSON1 used for in aeson?

Aeson provides FromJSON1 and ToJSON1 type classes. These are similar to the Eq1 and Show1 classes defined in the Data.Functor.Classes module.
My understanding of the Eq1 and Show1 classes is that they are needed to be able to express constraints on arguments of transformers without using extensions like FlexibleContexts and UndecidableInstances.
The example from the documentation in the Data.Functor.Classes module is as follows:
Assume we have a data type that acts as a transformer: T. For an example, let's have it be isomorphic to IdentityT:
data T f a = T (f a)
The kind of T is as follows:
T :: (* -> *) -> * -> *
If there is an Eq1 instance for f, it is possible to use it when writing the Eq1 instance for T f:
instance Eq1 f => Eq1 (T f) where
liftEq :: (a -> b -> Bool) -> T f a -> T f b -> Bool
liftEq eq (T fa1) (T fa2) = liftEq eq fa1 fa2
If we have an Eq1 instance for f, an Eq instance for a, and the Eq1 instance for T f above is in scope, we can easily write the Eq instance for T f a:
instance (Eq1 f, Eq a) => Eq (T f a) where
(==) :: T f a -> T f a -> Bool
(==) = eq1
The type of eq1 is defined as follows:
eq1 :: (Eq1 h, Eq a) => h a -> h a -> Bool
In our instance above, h becomes T f, so the type of eq1 can be thought of as the following:
eq1 :: Eq a => T f a -> T f a -> Bool
Now, the Eq1, Show1, etc classes make sense. It seems like it makes it easier to write instances of Eq, Show, etc for transformers.
However, I'm wondering what types FromJSON1 and ToJSON1 are used for in Aeson? I rarely have transformers that I want to turn to and from JSON.
Most of the data types I end up changing to JSON are normal types (not type constructors). That is to say, types with the kind *. I also uses types like Maybe with a kind of * -> *.
However, I don't think I often create ToJSON or FromJSON instances for transformers, like the T above. What is a transformer that is often used to go to and from JSON? Am I missing out on some helpful transformers?
Eq1 offers another feature that you haven't discussed in your exposition: it lets you write a function that calls (==) at many different types, without necessarily knowing ahead of time which types you will use it on.
I'll give a toy example; hopefully you can see through the apparent uselessness of this example to the reason Eq1 gives you some interesting powers.
Imagine you want to make a tree that is parameterized on the branching factor, so you parameterize it by the child container. So values might look like this:
{-# LANGUAGE GADTs #-}
data Tree m a where
Branch :: Tree m (m a) -> Tree m a
Leaf :: a -> Tree m a
For example, I can get binary trees with Tree Pair, trinary trees with Tree Triple, finger trees with Tree TwoThree, and rose trees with Tree [], where data Pair a = Pair a a, data Triple a = Triple a a a, and data TwoThree a = Two a a | Three a a a. Now I would like to write an Eq instance for this. If we only rely on Eq constraints, we can't get where we want to go. Let's try:
instance Eq (Tree m a) where
Leaf a == Leaf a' = a == a'
Branch t == Branch t' = t == t'
_ == _ = False
Naturally, GHC complains that it doesn't know how to compare a and a' for equality. So add Eq a to the context:
instance Eq a => Eq (Tree m a) where ...
Now GHC complains that it doesn't know how to compare m as for equality in the Branch case. Makes sense.
instance (Eq a, Eq (m a)) => Eq (Tree m a) where ...
Still no go! Now the implementation of (==) :: Tree m a -> Tree m a -> Bool has a recursive call to (==) :: Tree m (m a) -> Tree m (m a) -> Bool in its Branch case, hence must provide the context (Eq (m a), Eq (m (m a))) to make that recursive call. Okay, let's add that to the instance context...
instance (Eq a, Eq (m a), Eq (m (m a))) => Eq (Tree m a) where ...
Still no good. Now the recursive call has to prove even more stuff! What we'd really like to say is that if we have Eq b, then we have Eq (m b), for all bs and not just for the specific a being used as Tree's second parameter.
instance (Eq a, (forall b. Eq b => Eq (m b))) => Eq (Tree m a) where ...
Of course that's totally not a thing in Haskell. But Eq1 gives us that:
instance Eq1 m => Eq1 (Tree m) where
liftEq (==) (Leaf a) (Leaf a') = a == a'
liftEq (==) (Branch t) (Branch t') = liftEq (liftEq (==)) t t'
liftEq (==) _ _ = False
instance (Eq1 m, Eq a) => Eq (Tree m a) where
(==) = eq1
Here the Eq1 m constraint is serving the role we asked for before, namely, that all of (Eq a, Eq (m a), Eq (m (m a)), ...) are possible.
The ToJSON1 and FromJSON1 classes serve a similar role: they give you a single constraint that you can give that amounts to a potentially infinite collection of ToJSON and FromJSON constraints, so that you can choose which ToJSON or FromJSON constraint you need in a data-driven way and be guaranteed that it's available.

Function from `mappend` function to `Monoid` instance?

I have a data structure (it's a specific subclass of rose-tree that forms a lattice with greatest-lower bound and lowest-upper bound functions), and it supports two perfectly reasonable functions to serve as the Monoid class's mappend.
Is there any way to support anonymous Monoid instances in haskell? Is this an instance where I should consider using something like Template-Haskell to generate my typeclasses for me?
What I'd love is a makeMonoid :: (RT a -> RT a -> RT a) -> Monoid a to let me create the instance on the fly, but I understand that that's incoherent with the stock typesystem as I understand it.
I'm okay with it if I just need to pick a default merge function and write newtypes for other merges, just curious
You can create "local" instances of Monoid on the fly, using the tools in the reflection package. There's a ready-made example in the repository. This answer explains it a little.
This is a newtype wrapper over values of type a, on which we will define our Monoid instance.
newtype M a s = M { runM :: a } deriving (Eq,Ord)
Notice that there is a phantom type s that does not appear in the right hand side. It will carry extra information necessary for the local Monoid instance to work.
This is a record whose fields represent the two operation of the Monoid class:
data Monoid_ a = Monoid_ { mappend_ :: a -> a -> a, mempty_ :: a }
The following is the Monoid instance definition for M:
instance Reifies s (Monoid_ a) => Monoid (M a s) where
mappend a b = M $ mappend_ (reflect a) (runM a) (runM b)
mempty = a where a = M $ mempty_ (reflect a)
It says: "whenever s is a type-level representation of our Monoid dictionary Monoid_, we can reflect it back to obtain the dictionary, and use the fields to implement the Monoid operations for M".
Notice that the actual value a passed to reflect is not used, it is passed only as a "proxy" of type M a s that tells reflect which type (s) to use to "bring back the record".
The actual local instance is constructed using the reify function:
withMonoid :: (a -> a -> a) -> a -> (forall s. Reifies s (Monoid_ a) => M a s) -> a
withMonoid f z v = reify (Monoid_ f z) (runM . asProxyOf v)
asProxyOf :: f s -> Proxy s -> f s
asProxyOf a _ = a
The asProxyOf function is a trick to convince the compiler that the phantom type used in the monoid is the same as the one in the Proxy supplied by reify.

Type parameters constraints for instances of typeclasses with kind * -> *

Suppose I have Heap a type where Heap is type constructor of kind * -> *. Many basic operations on heap require the a type to be an instance of Ord type class.
data Heap a = ...
findMin :: Ord a => Heap a -> a
deleteMin :: Ord a => Heap a -> Heap a
I want to declare my Heap type as an instance of Foldable type class as soon as a type parameter is an instance of Ord type class (it will be easy to express via findMin and deleteMin functions).
This kind of relation can be easely expressed when we dealing with type classes that require type of kind *, like Show:
instance Show a => Show (Heap a) where
show h = ...
But I have problems with declaration of Foldable:
instance Foldable Heap where
-- Ouch, there is no `a` type parameter to put the constraint on!
foldr f z h = ...
Is it possible to put constraint on a type parameter in such instance declaration?
In general, no, when the type constructor itself is given the instance, there's no way to constrain the types it's applied to. Mostly this is a good thing, since it ensures that e.g. Functor instances are truly agnostic about their element type, which helps keep nice and predictable behavior nice and predictable.
Sometimes it's an annoyance instead, and the most common example is indeed needing an Ord constraint for a sorted data structure that could otherwise be a nice, well-behaved instance.
There are some experimental techniques involving stuff like constraint kinds, but in your specific case there's already a viable solution. If you look at the definition of Foldable, it says that only foldMap or foldr need to be implemented, so we'll consider those. Note the types:
foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
foldr :: (Foldable t) => (a -> b -> b) -> b -> t a -> b
In both cases, the type with a Foldable instance only appears once, as an argument to the function. Because of this, you can use GADTs with an Ord constraint:
data Heap a where
Heap :: (Ord a) => ...
By doing this, you'll need an Ord instance any time you create a Heap value, even an empty heap; but when you receive a Heap value, pattern matching on it will bring the Ord instance back into scope--even inside the Foldable instance!
Note that this doesn't help in many other situations:
fmap :: (Functor f) => (a -> b) -> f a -> f b
Here we can get an Ord instance on a, but we'd also need one for b, which isn't possible.
return :: (Monad m) => a -> m a
Here we need to provide an Ord instance as well.
Take a look at keys library on Hackage. Check if its FoldableWithKey type class is what you need.

Resources