
Dear Haskellers, While trying to understand the interconnection and hierarchy behind the important typeclasses, I stumbled upon the following question that I am not able to answer: There seems to be a hierachy of the type classes, in the sense, that the more powerfull a class is, the more fleixblility you have for combining them to complex programs. (Functor -> Applicative -> Arrow[Choice,Plus,Apply,..] -> Monad). It was nice to read in the Typeclassopedia, that ArrowApply and Monad are equivalent, which is shown by deriving two instances from each other: instance Monad m => ArrowApply (Kleisli m) instance ArrowApply a => Monad (a anyType) The logic seems to be, that if I can derive from every instance of class A an instance of class B, then A is more powerfull than B and (in general) it is easier to be of class B than of class A (e.g. more types can be made Applicatives, than Monads) So far, I think I can follow. But what really hit me was the Cokleisli type. Using it and the logic from above, I can show that ANY type class is more (or equally) powerfull than the Monad: instance AnyClass m => Monad (Cokleilsi m anyType) I know this makes no sense, but where is the fallacy? Why even bother with the above derivation, if any type class can be made into a monad? I can see, that the Monad instance from above does not really transform the type "a", but instead simply fix its first argument. But then on the other hand, the ArrowApply Instance does transform the "m" type (in a way similar to Cokleisli). If attention needs to be paid to the details, then what are they and why did they not matter above? Thanks, Johannes

I don't understand the final part of the question but here are some comments for the first part. I don't like the phrase:
the more powerfull a class is, the more fleixblility you have for combining them to complex programs
powerfull, more flexibility, complex programs -- are not so precise terms.
A => B
means that B can do everything that A can do and more (methods that are
specific to B). So if type is in B we can use all A's methods with it. Does
it make B more powerful or more flexible? Is Applicative less powerful than
a Monad? It depends on the program. If we don't ever need the B's specific
operations they will confuse us all the time. We are going to end up with
more complex program but not a better one. there are cases when Applicative
code is much better than a monadic one.
Anton
2013/5/28 Johannes Gerer
Dear Haskellers,
While trying to understand the interconnection and hierarchy behind the important typeclasses, I stumbled upon the following question that I am not able to answer:
There seems to be a hierachy of the type classes, in the sense, that the more powerfull a class is, the more fleixblility you have for combining them to complex programs. (Functor -> Applicative -> Arrow[Choice,Plus,Apply,..] -> Monad). It was nice to read in the Typeclassopedia, that ArrowApply and Monad are equivalent, which is shown by deriving two instances from each other:
instance Monad m => ArrowApply (Kleisli m) instance ArrowApply a => Monad (a anyType)
The logic seems to be, that if I can derive from every instance of class A an instance of class B, then A is more powerfull than B and (in general) it is easier to be of class B than of class A (e.g. more types can be made Applicatives, than Monads)
So far, I think I can follow. But what really hit me was the Cokleisli type. Using it and the logic from above, I can show that ANY type class is more (or equally) powerfull than the Monad:
instance AnyClass m => Monad (Cokleilsi m anyType)
I know this makes no sense, but where is the fallacy? Why even bother with the above derivation, if any type class can be made into a monad?
I can see, that the Monad instance from above does not really transform the type "a", but instead simply fix its first argument. But then on the other hand, the ArrowApply Instance does transform the "m" type (in a way similar to Cokleisli). If attention needs to be paid to the details, then what are they and why did they not matter above?
Thanks,
Johannes
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Thank you for the comments on the first part. While one can argue
about
the different meanings of powerful and flexible here, that's not the
question. The question is, about showing "A => B" using wrappers like
Kleisli or Cokleisli:
I can use Kleisli to show that a Monad can do everything an
ArrowApply
can do:
Instance Monad m => ArrowApply (Kleisli m)
By the same argument, could'nt I say, that any type class (call it
AnyClass) can do everything a Monad can:
instance AnyClass m => Monad (Cokleilsi m ())
Another way to look at the question:
An Applicative lets you build static trees using the available
combinators. Arrows let you combine effectful computations into
networks
or graphs and monad even more complex things. But again Cokleilsi
crashes the party, as it gives you the Monad's combinators for any
type
and consequently you can build almost anything. I do not understand,
what this tells me!
Johannes
On Tue, May 28, 2013 at 3:04 PM, Anton Kholomiov
I don't understand the final part of the question but here are some comments for the first part.
I don't like the phrase:
the more powerfull a class is, the more fleixblility you have for combining them to complex programs
powerfull, more flexibility, complex programs -- are not so precise terms.
A => B
means that B can do everything that A can do and more (methods that are specific to B). So if type is in B we can use all A's methods with it. Does it make B more powerful or more flexible? Is Applicative less powerful than a Monad? It depends on the program. If we don't ever need the B's specific operations they will confuse us all the time. We are going to end up with more complex program but not a better one. there are cases when Applicative code is much better than a monadic one.
Anton
2013/5/28 Johannes Gerer
Dear Haskellers,
While trying to understand the interconnection and hierarchy behind the important typeclasses, I stumbled upon the following question that I am not able to answer:
There seems to be a hierachy of the type classes, in the sense, that the more powerfull a class is, the more fleixblility you have for combining them to complex programs. (Functor -> Applicative -> Arrow[Choice,Plus,Apply,..] -> Monad). It was nice to read in the Typeclassopedia, that ArrowApply and Monad are equivalent, which is shown by deriving two instances from each other:
instance Monad m => ArrowApply (Kleisli m) instance ArrowApply a => Monad (a anyType)
The logic seems to be, that if I can derive from every instance of class A an instance of class B, then A is more powerfull than B and (in general) it is easier to be of class B than of class A (e.g. more types can be made Applicatives, than Monads)
So far, I think I can follow. But what really hit me was the Cokleisli type. Using it and the logic from above, I can show that ANY type class is more (or equally) powerfull than the Monad:
instance AnyClass m => Monad (Cokleilsi m anyType)
I know this makes no sense, but where is the fallacy? Why even bother with the above derivation, if any type class can be made into a monad?
I can see, that the Monad instance from above does not really transform the type "a", but instead simply fix its first argument. But then on the other hand, the ArrowApply Instance does transform the "m" type (in a way similar to Cokleisli). If attention needs to be paid to the details, then what are they and why did they not matter above?
Thanks,
Johannes
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, May 28, 2013 at 04:42:35PM +0200, Johannes Gerer wrote:
By the same argument, could'nt I say, that any type class (call it AnyClass) can do everything a Monad can:
instance AnyClass m => Monad (Cokleilsi m ())
That doesn't say that AnyClass can do anything a Monad can. "AnyClass m => Monad m" would say that, but that's not what you've got. What you've got is that "Cokleisli m ()" i.e. "(->) m ()" is a Monad for any "m". This is not surprising. The implementation is the same as the Reader monad. Check out the instance implementations for "Monad (Reader r)" and "Monad (CoKleisli w a)". You will find they are the same. http://hackage.haskell.org/packages/archive/mtl/1.1.0.2/doc/html/src/Control... http://hackage.haskell.org/packages/archive/comonad/3.0.0.2/doc/html/src/Con... Tom

That makes sense. But why does
instance Monad m => ArrowApply (Kleisli m)
show that a Monad can do anything an ArrowApply can (and the two are
thus equivalent)?
On Tue, May 28, 2013 at 5:17 PM, Tom Ellis
On Tue, May 28, 2013 at 04:42:35PM +0200, Johannes Gerer wrote:
By the same argument, could'nt I say, that any type class (call it AnyClass) can do everything a Monad can:
instance AnyClass m => Monad (Cokleilsi m ())
That doesn't say that AnyClass can do anything a Monad can. "AnyClass m => Monad m" would say that, but that's not what you've got.
What you've got is that "Cokleisli m ()" i.e. "(->) m ()" is a Monad for any "m". This is not surprising. The implementation is the same as the Reader monad.
Check out the instance implementations for "Monad (Reader r)" and "Monad (CoKleisli w a)". You will find they are the same.
http://hackage.haskell.org/packages/archive/mtl/1.1.0.2/doc/html/src/Control... http://hackage.haskell.org/packages/archive/comonad/3.0.0.2/doc/html/src/Con...
Tom
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, May 28, 2013 at 05:21:58PM +0200, Johannes Gerer wrote:
That makes sense. But why does
instance Monad m => ArrowApply (Kleisli m)
show that a Monad can do anything an ArrowApply can (and the two are thus equivalent)?
I've tried to chase around the equivalence between these two before, and I didn't find the algebra simple. I'll give an outline. In non-Haskell notation 1) instance Monad m => ArrowApply (Kleisli m) means that if "m" is a Monad then "_ -> m _" is an ArrowApply. 2) instance ArrowApply a => Monad (a anyType) means that if "_ ~> _" is an ArrowApply then "a ~> _" is a Monad. One direction seems easy: for a Monad m, 1) gives that "_ -> m _" is an ArrowApply. By 2), "() -> m _" is a Monad. It is equivalent to the Monad m we started with. Given an ArrowApply "_ ~> _", 2) shows that "() ~> _" is a Monad. Thus by 1) "_ -> (() ~> _)" is an ArrowApply. I believe this should be the same type as "_ ~> _" but I don't see how to demonstrate the isomorphsim here. Tom

Ok, now I see a difference, why Kleisli can be used to relate
typeclasses (like Monad and ArrowApply) and Cokleisli can not:
"Kleisli m () _" = "() -> m _" is isomorphic to "m _"
whereas
"Cokleisli m () _" = "m _ -> ()" is not.
Can somebody point out the relevant category theoretical concepts,
that are at work here?
On Tue, May 28, 2013 at 5:43 PM, Tom Ellis
On Tue, May 28, 2013 at 05:21:58PM +0200, Johannes Gerer wrote:
That makes sense. But why does
instance Monad m => ArrowApply (Kleisli m)
show that a Monad can do anything an ArrowApply can (and the two are thus equivalent)?
I've tried to chase around the equivalence between these two before, and I didn't find the algebra simple. I'll give an outline.
In non-Haskell notation
1) instance Monad m => ArrowApply (Kleisli m)
means that if "m" is a Monad then "_ -> m _" is an ArrowApply.
2) instance ArrowApply a => Monad (a anyType)
means that if "_ ~> _" is an ArrowApply then "a ~> _" is a Monad.
One direction seems easy: for a Monad m, 1) gives that "_ -> m _" is an ArrowApply. By 2), "() -> m _" is a Monad. It is equivalent to the Monad m we started with.
Given an ArrowApply "_ ~> _", 2) shows that "() ~> _" is a Monad. Thus by 1) "_ -> (() ~> _)" is an ArrowApply. I believe this should be the same type as "_ ~> _" but I don't see how to demonstrate the isomorphsim here.
Tom
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

What about these two very simple type classes. Are they equivalent?
(As Monad and ArrowApply)
(This actually compiles in GHC)
class Pointed f where
pure :: a -> f a
class Unit f where
unit :: f a a
newtype UnitPointed f a = UnitPointed f a a
instance Unit f => Pointed (UnitPointed f) where
pure f = UnitPointed unit
newtype Kleisli f a b = Kleisli (a -> f b)
instance Pointed f => Unit (Kleisli f) where
unit = Kleisli pure
On Tue, May 28, 2013 at 6:05 PM, Johannes Gerer
Ok, now I see a difference, why Kleisli can be used to relate typeclasses (like Monad and ArrowApply) and Cokleisli can not:
"Kleisli m () _" = "() -> m _" is isomorphic to "m _"
whereas
"Cokleisli m () _" = "m _ -> ()" is not.
Can somebody point out the relevant category theoretical concepts, that are at work here?
On Tue, May 28, 2013 at 5:43 PM, Tom Ellis
wrote: On Tue, May 28, 2013 at 05:21:58PM +0200, Johannes Gerer wrote:
That makes sense. But why does
instance Monad m => ArrowApply (Kleisli m)
show that a Monad can do anything an ArrowApply can (and the two are thus equivalent)?
I've tried to chase around the equivalence between these two before, and I didn't find the algebra simple. I'll give an outline.
In non-Haskell notation
1) instance Monad m => ArrowApply (Kleisli m)
means that if "m" is a Monad then "_ -> m _" is an ArrowApply.
2) instance ArrowApply a => Monad (a anyType)
means that if "_ ~> _" is an ArrowApply then "a ~> _" is a Monad.
One direction seems easy: for a Monad m, 1) gives that "_ -> m _" is an ArrowApply. By 2), "() -> m _" is a Monad. It is equivalent to the Monad m we started with.
Given an ArrowApply "_ ~> _", 2) shows that "() ~> _" is a Monad. Thus by 1) "_ -> (() ~> _)" is an ArrowApply. I believe this should be the same type as "_ ~> _" but I don't see how to demonstrate the isomorphsim here.
Tom
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, May 28, 2013 at 09:09:48PM +0200, Johannes Gerer wrote:
What about these two very simple type classes. Are they equivalent? [...] class Pointed f where pure :: a -> f a
class Unit f where unit :: f a a
newtype UnitPointed f a = UnitPointed f a a instance Unit f => Pointed (UnitPointed f) where pure f = UnitPointed unit
newtype Kleisli f a b = Kleisli (a -> f b) instance Pointed f => Unit (Kleisli f) where unit = Kleisli pure
This is implausible, since "pure f" does not depend on "f".

Dear Tom,
I really appreciate your help, but If I could ask the perfect question
I probably would already know the answer... My example should not
prove anything, instead they collectively show, that I am missing
something. And it is not the fact, that "pure f does not depend on f."
If, however, this makes all the difference, I have to ask, why was
plausability and looking at the actual definition (not just the types)
not important for the other examples.
But I think my problem lies somewhere else. Maybe all would become
evident, if I knew the rigorous definition of "A is more general than
B" in this context. Especially when A is a class of type, that takes
two arguments (i.e. Unit and Arrow) and B for ones, that takes only
one (like Monad, Pure,..)
Thanks again!
Johannes
On Tue, May 28, 2013 at 11:11 PM, Tom Ellis
On Tue, May 28, 2013 at 09:09:48PM +0200, Johannes Gerer wrote:
What about these two very simple type classes. Are they equivalent? [...] class Pointed f where pure :: a -> f a
class Unit f where unit :: f a a
newtype UnitPointed f a = UnitPointed f a a instance Unit f => Pointed (UnitPointed f) where pure f = UnitPointed unit
newtype Kleisli f a b = Kleisli (a -> f b) instance Pointed f => Unit (Kleisli f) where unit = Kleisli pure
This is implausible, since "pure f" does not depend on "f".
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, May 28, 2013 at 11:22:22PM +0200, Johannes Gerer wrote:
I have to ask, why was plausability and looking at the actual definition (not just the types) not important for the other examples.
It would also be important to check the definitions in the other examples too, but it's hard enough to get the types to match!
But I think my problem lies somewhere else. Maybe all would become evident, if I knew the rigorous definition of "A is more general than B" in this context. Especially when A is a class of type, that takes two arguments (i.e. Unit and Arrow) and B for ones, that takes only one (like Monad, Pure,..)
I'm not sure what the right definition is. You are right that it is far from obvious (at least to you and me!). For a definition of equivalence, I feel it should go something like this: To every instance a of A I can assign an instance b of B, and to every instance b of B I can assign an instance a' of A. Moreover there should be a function polymorphic in all parameters between a and a', which has a polymorphic inverse. (And likewise for A and B swapped). These functions might need to be required to commute with all member functions of A. Perhaps this is perfectly obvious and well known, but I haven't managed to work it out on my own. Tom
participants (3)
-
Anton Kholomiov
-
Johannes Gerer
-
Tom Ellis