Swapping parameters and type classes
Hi all If I have this type: data Foo a b = ... and this class class Bar (x :: * -> *) where ... I can imagine two ways to make Foo an instance of Bar. Either I must "apply" the 'a' or the 'b' in (Foo a b). Otherwise it will not have the right kind. To "apply" the 'a' I can do: instance Bar (Foo a) where ... But what if I want to "apply" the 'b' ? How do I do that ? Greetings, Mads Lindstrøm
On 9/16/07, Mads Lindstrøm <mads_lindstroem@yahoo.dk> wrote:
Hi all
If I have this type:
data Foo a b = ...
and this class
class Bar (x :: * -> *) where ...
I can imagine two ways to make Foo an instance of Bar. Either I must "apply" the 'a' or the 'b' in (Foo a b). Otherwise it will not have the right kind. To "apply" the 'a' I can do:
instance Bar (Foo a) where ...
But what if I want to "apply" the 'b' ? How do I do that ?
One easy way would be to create a newtype with the type parameters swapped: newtype Oof b a = Oof (Foo a b) instance Bar (Oof b) where ... Of course, if you want to partially apply the second parameter of a function, you use 'flip'. I thought for a while about whether there's some sort of typeclass hackery which is directly parallel to the use of 'flip', but couldn't come up with anything. Anyone? -Brent
On 9/16/07, Mads Lindstrøm <mads_lindstroem@yahoo.dk> wrote:
But what if I want to "apply" the 'b' ? How do I do that ?
The following uses type families (functions) and compiles under GHC HEAD: {-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -XTypeSynonymInstances #-} data Foo a b class Bar (x :: * -> *) instance Bar (Foo a) type family BarB a b :: * -> * type instance BarB a b = Foo b instance Bar (BarB a b) regards, Bas van Dijk
On Sun, Sep 16, 2007 at 10:45:39PM +0200, Bas van Dijk wrote:
On 9/16/07, Mads Lindstrøm <mads_lindstroem@yahoo.dk> wrote:
But what if I want to "apply" the 'b' ? How do I do that ?
The following uses type families (functions) and compiles under GHC HEAD:
{-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -XTypeSynonymInstances #-}
Eek! That should be: {-# LANGUAGE TypeFamilies, EmptyDataDecls, TypeSynonymInstances #-} Modulo the fact that only GHC support type families at the moment, the latter will be portable... (Ian/Simon: I've seen this several times now. Maybe there should be a warning for -X in OPTIONS? Is that even feasable?) Stefan
On Sun, Sep 16, 2007 at 01:59:02PM -0700, Stefan O'Rear wrote:
{-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -XTypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies, EmptyDataDecls, TypeSynonymInstances #-}
(Ian/Simon: I've seen this several times now. Maybe there should be a warning for -X in OPTIONS? Is that even feasable?)
Currently we can't even give a warning when completely deprecated flags are used, but when fixing that I think we should also do as you suggest. Thanks Ian
Hi Bas Thank you for the answer. I tried to "fill in some blanks" in the example you gave. And mostly got a lot of context reduction stack overflows :( Here is my example (a little closer to what I actually need): data Foo a b = Foo { first :: a, second :: b } class Bar (x :: * -> *) where foo :: x a -> a instance Bar (Foo a) where foo x = second x type family BarB a b :: * -> * type instance BarB a b = Foo b instance Bar (BarB a b) where foo x = second x -- this unexpectedly works! -- foo x = first x -- This unexpectedly gives context reduction stack overflow What surprises me is that I still need to look at `second`, even though I use BarB. I thought I was swapping the parameters. Whats more changing the line: type instance BarB a b = Foo b to type instance BarB a b = Foo a -- the last letter changed has no effect. Greetings, Mads Lindstrøm P.s. Why can we not just have the option of being explicit about which type parameters are applied? Something like: "instance Bar (apply a. Foo a b)" which would apply a and be identical to "instance Bar (Foo a)" "instance Bar (apply b. Foo a b)" which would apply b and be what I am trying to achieve. It would seem a lot more natural to me. But maybe there are other reasons why type families are a better solution? I do not know if I use the right terminology when saying "apply". Please correct if there is more correct terms. Bas van Dijk:
On 9/16/07, Mads Lindstrøm <mads_lindstroem@yahoo.dk> wrote:
But what if I want to "apply" the 'b' ? How do I do that ?
The following uses type families (functions) and compiles under GHC HEAD:
{-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -XTypeSynonymInstances #-}
data Foo a b
class Bar (x :: * -> *)
instance Bar (Foo a)
type family BarB a b :: * -> * type instance BarB a b = Foo b
instance Bar (BarB a b)
regards,
Bas van Dijk
On 9/17/07, Mads Lindstrøm <mads_lindstroem@yahoo.dk> wrote:
Hi Bas
Thank you for the answer.
I tried to "fill in some blanks" in the example you gave. And mostly got a lot of context reduction stack overflows :(
Here is my example (a little closer to what I actually need):
data Foo a b = Foo { first :: a, second :: b }
class Bar (x :: * -> *) where foo :: x a -> a
instance Bar (Foo a) where foo x = second x
type family BarB a b :: * -> * type instance BarB a b = Foo b
instance Bar (BarB a b) where foo x = second x -- this unexpectedly works! -- foo x = first x -- This unexpectedly gives context reduction stack overflow
What surprises me is that I still need to look at `second`, even though I use BarB. I thought I was swapping the parameters. Whats more changing the line:
type instance BarB a b = Foo b
to
type instance BarB a b = Foo a -- the last letter changed
has no effect.
Greetings,
Mads Lindstrøm
P.s. Why can we not just have the option of being explicit about which type parameters are applied? Something like:
"instance Bar (apply a. Foo a b)" which would apply a and be identical to "instance Bar (Foo a)" "instance Bar (apply b. Foo a b)" which would apply b and be what I am trying to achieve.
It would seem a lot more natural to me. But maybe there are other reasons why type families are a better solution?
I do not know if I use the right terminology when saying "apply". Please correct if there is more correct terms.
Bas van Dijk:
On 9/16/07, Mads Lindstrøm <mads_lindstroem@yahoo.dk> wrote:
But what if I want to "apply" the 'b' ? How do I do that ?
The following uses type families (functions) and compiles under GHC HEAD:
{-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -XTypeSynonymInstances #-}
data Foo a b
class Bar (x :: * -> *)
instance Bar (Foo a)
type family BarB a b :: * -> * type instance BarB a b = Foo b
instance Bar (BarB a b)
regards,
Bas van Dijk
Mads, my sollution was not correct. This is why: instance Bar (BarB a b) is equal to: instance Bar (Foo b) which is just equal to: instance Bar (Foo a) The 'b' in 'instance Bar (Foo b)' has nothing to do with the 'b' in 'Foo a b'. In fact the 'b' in 'BarB a b' is equal to the 'a' in 'Foo a b'. Sorry that I bothered you with this but like I said, it was late and I already consumed some wine. Not a good combination when programming ;-) Bas.
This thread is certainly interesting, but it would be better on Haskell-café@haskell.org. The Haskell@haskell.org list is intended as a low-bandwidth list for announcements and the like. Thanks! Simon | -----Original Message----- | From: haskell-bounces@haskell.org [mailto:haskell-bounces@haskell.org] | On Behalf Of Bas van Dijk | Sent: 17 September 2007 20:17 | To: Mads Lindstrøm | Cc: haskell@haskell.org | Subject: Re: [Haskell] Swapping parameters and type classes | | On 9/17/07, Mads Lindstrøm <mads_lindstroem@yahoo.dk> wrote: | > Hi Bas | > | > Thank you for the answer. | > | > I tried to "fill in some blanks" in the example you gave. And mostly | got | > a lot of context reduction stack overflows :( | > | > Here is my example (a little closer to what I actually need): | > | > data Foo a b = Foo { first :: a, second :: b } | > | > class Bar (x :: * -> *) where | > foo :: x a -> a | > | > instance Bar (Foo a) where | > foo x = second x | > | > type family BarB a b :: * -> * | > type instance BarB a b = Foo b | > | > instance Bar (BarB a b) where | > foo x = second x -- this unexpectedly works! | > -- foo x = first x -- This unexpectedly gives context reduction | stack overflow | > | > What surprises me is that I still need to look at `second`, even | though | > I use BarB. I thought I was swapping the parameters. Whats more | changing | > the line: | > | > type instance BarB a b = Foo b | > | > to | > | > type instance BarB a b = Foo a -- the last letter changed | > | > has no effect. | > | > | > Greetings, | > | > Mads Lindstrøm | > | > P.s. Why can we not just have the option of being explicit about | which type parameters are applied? Something like: | > | > "instance Bar (apply a. Foo a b)" which would apply a and be | identical to "instance Bar (Foo a)" | > "instance Bar (apply b. Foo a b)" which would apply b and be what I | am trying to achieve. | > | > It would seem a lot more natural to me. But maybe there are other | reasons why type families are a better solution? | > | > I do not know if I use the right terminology when saying "apply". | Please correct if there is more correct terms. | > | > | > Bas van Dijk: | > > On 9/16/07, Mads Lindstrøm <mads_lindstroem@yahoo.dk> wrote: | > > > But what if I want to "apply" the 'b' ? How do I do that ? | > > | > > The following uses type families (functions) and compiles under GHC | HEAD: | > > | > > {-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls - | XTypeSynonymInstances #-} | > > | > > data Foo a b | > > | > > class Bar (x :: * -> *) | > > | > > instance Bar (Foo a) | > > | > > type family BarB a b :: * -> * | > > type instance BarB a b = Foo b | > > | > > instance Bar (BarB a b) | > > | > > | > > regards, | > > | > > Bas van Dijk | > | > | | Mads, my sollution was not correct. | | This is why: | | instance Bar (BarB a b) | | is equal to: | | instance Bar (Foo b) | | which is just equal to: | | instance Bar (Foo a) | | The 'b' in 'instance Bar (Foo b)' has nothing to do with the 'b' in | 'Foo a b'. In fact the 'b' in 'BarB a b' is equal to the 'a' in 'Foo a | b'. | | Sorry that I bothered you with this but like I said, it was late and I | already consumed some wine. Not a good combination when programming | ;-) | | Bas. | _______________________________________________ | Haskell mailing list | Haskell@haskell.org | http://www.haskell.org/mailman/listinfo/haskell
participants (6)
-
Bas van Dijk -
Brent Yorgey -
Ian Lynagh -
Mads Lindstrøm -
Simon Peyton-Jones -
Stefan O'Rear