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 <kuerzn@gmail.com>
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 <anton.kholomiov@gmail.com> wrote:
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 <kuerzn@gmail.com>
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 <tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> wrote:
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 <tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> 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
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 <kuerzn@gmail.com> wrote:
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 <tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> 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 <tom-lists-haskell-cafe-2013@jaguarpaw.co.uk> wrote:
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