Bas van Dijk | 22 Dec 00:45 2011
Picon

ConstraintKinds and default associated empty constraints

I'm playing a bit with the new ConstraintKinds feature in GHC
7.4.1-rc1. I'm trying to give the Functor class an associated
constraint so that we can make Set an instance of Functor. The
following code works but I wonder if the trick with: class Empty a;
instance Empty a, is the recommended way to do this:

{-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}

import GHC.Prim (Constraint)

import Prelude hiding (Functor, fmap)

import           Data.Set (Set)
import qualified Data.Set as S (map, fromList)

class Functor f where
    type C f :: * -> Constraint
    type C f = Empty

    fmap :: (C f a, C f b) => (a -> b) -> f a -> f b

class Empty a; instance Empty a

instance Functor Set where
    type C Set = Ord
    fmap = S.map

instance Functor [] where
    fmap = map

(Continue reading)

wagnerdm | 22 Dec 01:58 2011

Re: ConstraintKinds and default associated empty constraints

Quoting Bas van Dijk <v.dijk.bas <at> gmail.com>:

> I'm playing a bit with the new ConstraintKinds feature in GHC
> 7.4.1-rc1. I'm trying to give the Functor class an associated
> constraint so that we can make Set an instance of Functor. The
> following code works but I wonder if the trick with: class Empty a;
> instance Empty a, is the recommended way to do this:

Maybe something like this?

class Functor f where
     type C f a :: Constraint
     type C f a = ()

instance Functor Set where
     type C Set a = Ord a

~d
Bas van Dijk | 22 Dec 10:34 2011
Picon

Re: ConstraintKinds and default associated empty constraints

On 22 December 2011 01:58,  <wagnerdm <at> seas.upenn.edu> wrote:
> Quoting Bas van Dijk <v.dijk.bas <at> gmail.com>:
>
>> I'm playing a bit with the new ConstraintKinds feature in GHC
>> 7.4.1-rc1. I'm trying to give the Functor class an associated
>> constraint so that we can make Set an instance of Functor. The
>> following code works but I wonder if the trick with: class Empty a;
>> instance Empty a, is the recommended way to do this:
>
>
> Maybe something like this?
>
> class Functor f where
>    type C f a :: Constraint
>    type C f a = ()
>
> instance Functor Set where
>    type C Set a = Ord a
>
> ~d
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users <at> haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Yes I already tried that, but the following gives a type error:

instance Functor [] where
    fmap = map
(Continue reading)

Simon Peyton-Jones | 22 Dec 09:31 2011
Picon

RE: ConstraintKinds and default associated empty constraints

What about 

class Functor f where
    type C f :: * -> Constraint
    type C f = ()

After all, just as (Ord a, Show a) is a contraint, so is ().

Simon

| -----Original Message-----
| From: glasgow-haskell-users-bounces <at> haskell.org [mailto:glasgow-haskell-
| users-bounces <at> haskell.org] On Behalf Of Bas van Dijk
| Sent: 21 December 2011 23:46
| To: glasgow-haskell-users <at> haskell.org
| Subject: ConstraintKinds and default associated empty constraints
| 
| I'm playing a bit with the new ConstraintKinds feature in GHC
| 7.4.1-rc1. I'm trying to give the Functor class an associated
| constraint so that we can make Set an instance of Functor. The
| following code works but I wonder if the trick with: class Empty a;
| instance Empty a, is the recommended way to do this:
| 
| {-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}
| 
| import GHC.Prim (Constraint)
| 
| import Prelude hiding (Functor, fmap)
| 
| import           Data.Set (Set)
(Continue reading)

Bas van Dijk | 22 Dec 10:37 2011
Picon

Re: ConstraintKinds and default associated empty constraints

On 22 December 2011 09:31, Simon Peyton-Jones <simonpj <at> microsoft.com> wrote:
> What about
>
> class Functor f where
>    type C f :: * -> Constraint
>    type C f = ()
>
> After all, just as (Ord a, Show a) is a contraint, so is ().

But there's a kind mis-match there. `C f` should have kind `* ->
Constraint` but () has kind *. Or do I have to enable some language
extension to make this work?

Thanks,

Bas

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Gábor Lehel | 22 Dec 14:53 2011
Picon

Re: ConstraintKinds and default associated empty constraints

On Thu, Dec 22, 2011 at 12:45 AM, Bas van Dijk <v.dijk.bas <at> gmail.com> wrote:
> I'm playing a bit with the new ConstraintKinds feature in GHC
> 7.4.1-rc1. I'm trying to give the Functor class an associated
> constraint so that we can make Set an instance of Functor. The
> following code works but I wonder if the trick with: class Empty a;
> instance Empty a, is the recommended way to do this:
>
> {-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}
>
> import GHC.Prim (Constraint)
>
> import Prelude hiding (Functor, fmap)
>
> import           Data.Set (Set)
> import qualified Data.Set as S (map, fromList)
>
> class Functor f where
>     type C f :: * -> Constraint
>     type C f = Empty
>
>     fmap :: (C f a, C f b) => (a -> b) -> f a -> f b
>
> class Empty a; instance Empty a
>
> instance Functor Set where
>     type C Set = Ord
>     fmap = S.map
>
> instance Functor [] where
>     fmap = map
(Continue reading)

Edward Kmett | 22 Dec 18:02 2011
Picon

Re: ConstraintKinds and default associated empty constraints

On Wed, Dec 21, 2011 at 6:45 PM, Bas van Dijk <v.dijk.bas <at> gmail.com> wrote:
I'm playing a bit with the new ConstraintKinds feature in GHC
7.4.1-rc1. I'm trying to give the Functor class an associated
constraint so that we can make Set an instance of Functor. The
following code works but I wonder if the trick with: class Empty a;
instance Empty a, is the recommended way to do this:

{-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}

import GHC.Prim (Constraint)

import Prelude hiding (Functor, fmap)

import           Data.Set (Set)
import qualified Data.Set as S (map, fromList)

class Functor f where
    type C f :: * -> Constraint
    type C f = Empty

    fmap :: (C f a, C f b) => (a -> b) -> f a -> f b

class Empty a; instance Empty a

instance Functor Set where
    type C Set = Ord
    fmap = S.map

instance Functor [] where
    fmap = map

testList = fmap (+1) [1,2,3]
testSet  = fmap (+1) (S.fromList [1,2,3])

Cheers and thanks for a great new feature!

Bas


This is the same solution I wound up with in


Adding an argument to the family would work but is somewhat unsatisfying as it mucks with polymorphic recursive use of the dictionary, and with placing constraints on constraints, so I prefer to keep as few arguments as possible.

You can go farther with Functor by using polymorphic kinds and indexing the source and destination Category as well as the class of objects in the category.

I should probably write up what I've done with this, but doing so lets you have real product and coproduct Category instances, which were previously not possible (a fact which in part drove me to write all the semigroupoid code i have on hackage.

-Edward
_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Simon Peyton-Jones | 23 Dec 10:42 2011
Picon

RE: ConstraintKinds and default associated empty constraints

it’s a bug.  I’m fixing it.


Simon

 

From: glasgow-haskell-users-bounces <at> haskell.org [mailto:glasgow-haskell-users-bounces <at> haskell.org] On Behalf Of Edward Kmett
Sent: 22 December 2011 17:03
To: Bas van Dijk
Cc: glasgow-haskell-users <at> haskell.org
Subject: Re: ConstraintKinds and default associated empty constraints

 

On Wed, Dec 21, 2011 at 6:45 PM, Bas van Dijk <v.dijk.bas <at> gmail.com> wrote:

I'm playing a bit with the new ConstraintKinds feature in GHC
7.4.1-rc1. I'm trying to give the Functor class an associated
constraint so that we can make Set an instance of Functor. The
following code works but I wonder if the trick with: class Empty a;
instance Empty a, is the recommended way to do this:

{-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}

import GHC.Prim (Constraint)

import Prelude hiding (Functor, fmap)

import           Data.Set (Set)
import qualified Data.Set as S (map, fromList)

class Functor f where
    type C f :: * -> Constraint
    type C f = Empty

    fmap :: (C f a, C f b) => (a -> b) -> f a -> f b

class Empty a; instance Empty a

instance Functor Set where
    type C Set = Ord
    fmap = S.map

instance Functor [] where
    fmap = map

testList = fmap (+1) [1,2,3]
testSet  = fmap (+1) (S.fromList [1,2,3])

Cheers and thanks for a great new feature!

Bas

 

This is the same solution I wound up with in

 

 

Adding an argument to the family would work but is somewhat unsatisfying as it mucks with polymorphic recursive use of the dictionary, and with placing constraints on constraints, so I prefer to keep as few arguments as possible.

 

You can go farther with Functor by using polymorphic kinds and indexing the source and destination Category as well as the class of objects in the category.

 

I should probably write up what I've done with this, but doing so lets you have real product and coproduct Category instances, which were previously not possible (a fact which in part drove me to write all the semigroupoid code i have on hackage.

 

-Edward

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Edward Kmett | 23 Dec 16:05 2011
Picon

Re: ConstraintKinds and default associated empty constraints

Fair enough.

So if I understand you correctly, () is becoming more overloaded as to its kind? 

Right now it seems it is either * or Constraint depending on context. 

As I understand you, fixing this seems to indicate that () could have any 'a -> Constraint' kind as well.

This raises similar questions about (,) and how to build 'a -> Constraint' products nicely.

Sent from my iPad

On Dec 23, 2011, at 4:42 AM, Simon Peyton-Jones <simonpj <at> microsoft.com> wrote:

<!-- /* Font Definitions */ <at> font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4;} <at> font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4;} <at> font-face {font-family:Tahoma; panose-1:2 11 6 4 3 5 4 4 2 4;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {margin:0cm; margin-bottom:.0001pt; font-size:12.0pt; font-family:"Times New Roman","serif";} a:link, span.MsoHyperlink {mso-style-priority:99; color:blue; text-decoration:underline;} a:visited, span.MsoHyperlinkFollowed {mso-style-priority:99; color:purple; text-decoration:underline;} span.EmailStyle17 {mso-style-type:personal-reply; font-family:"Calibri","sans-serif"; color:#1F497D;} .MsoChpDefault {mso-style-type:export-only;} <at> page WordSection1 {size:612.0pt 792.0pt; margin:72.0pt 72.0pt 72.0pt 72.0pt;} div.WordSection1 {page:WordSection1;} -->

it’s a bug.  I’m fixing it.


Simon

 

From: glasgow-haskell-users-bounces <at> haskell.org [mailto:glasgow-haskell-users-bounces <at> haskell.org] On Behalf Of Edward Kmett
Sent: 22 December 2011 17:03
To: Bas van Dijk
Cc: glasgow-haskell-users <at> haskell.org
Subject: Re: ConstraintKinds and default associated empty constraints

 

On Wed, Dec 21, 2011 at 6:45 PM, Bas van Dijk <v.dijk.bas <at> gmail.com> wrote:

I'm playing a bit with the new ConstraintKinds feature in GHC
7.4.1-rc1. I'm trying to give the Functor class an associated
constraint so that we can make Set an instance of Functor. The
following code works but I wonder if the trick with: class Empty a;
instance Empty a, is the recommended way to do this:

{-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}

import GHC.Prim (Constraint)

import Prelude hiding (Functor, fmap)

import           Data.Set (Set)
import qualified Data.Set as S (map, fromList)

class Functor f where
    type C f :: * -> Constraint
    type C f = Empty

    fmap :: (C f a, C f b) => (a -> b) -> f a -> f b

class Empty a; instance Empty a

instance Functor Set where
    type C Set = Ord
    fmap = S.map

instance Functor [] where
    fmap = map

testList = fmap (+1) [1,2,3]
testSet  = fmap (+1) (S.fromList [1,2,3])

Cheers and thanks for a great new feature!

Bas

 

This is the same solution I wound up with in

 

 

Adding an argument to the family would work but is somewhat unsatisfying as it mucks with polymorphic recursive use of the dictionary, and with placing constraints on constraints, so I prefer to keep as few arguments as possible.

 

You can go farther with Functor by using polymorphic kinds and indexing the source and destination Category as well as the class of objects in the category.

 

I should probably write up what I've done with this, but doing so lets you have real product and coproduct Category instances, which were previously not possible (a fact which in part drove me to write all the semigroupoid code i have on hackage.

 

-Edward

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Simon Peyton-Jones | 23 Dec 16:17 2011
Picon

RE: ConstraintKinds and default associated empty constraints

Right now it seems it is either * or Constraint depending on context. 

 

Correct.  Tuple bracket are used for both types and Constraints, and we have to decide which from context. 

 

            As I understand you, fixing this seems to indicate that () could have any 'a -> Constraint' kind as well.

 

No.  () has kind * or Constraint, depending on context, never a -> Constraint.

Similarly (,) has kind * -> * -> * or Constraint -> Constraint -> Constraint, depending on context.

 

Imaging that there are two sorts of parens, one for types and one for constraints.  We figure out which is intended from context.

 

S

 

From: Edward Kmett [mailto:ekmett <at> gmail.com]
Sent: 23 December 2011 15:05
To: Simon Peyton-Jones
Cc: Bas van Dijk; glasgow-haskell-users <at> haskell.org
Subject: Re: ConstraintKinds and default associated empty constraints

 

Fair enough.

 

So if I understand you correctly, () is becoming more overloaded as to its kind? 

 

Right now it seems it is either * or Constraint depending on context. 

 

As I understand you, fixing this seems to indicate that () could have any 'a -> Constraint' kind as well.

 

This raises similar questions about (,) and how to build 'a -> Constraint' products nicely.


Sent from my iPad


On Dec 23, 2011, at 4:42 AM, Simon Peyton-Jones <simonpj <at> microsoft.com> wrote:

it’s a bug.  I’m fixing it.


Simon

 

From: glasgow-haskell-users-bounces <at> haskell.org [mailto:glasgow-haskell-users-bounces <at> haskell.org] On Behalf Of Edward Kmett
Sent: 22 December 2011 17:03
To: Bas van Dijk
Cc: glasgow-haskell-users <at> haskell.org
Subject: Re: ConstraintKinds and default associated empty constraints

 

On Wed, Dec 21, 2011 at 6:45 PM, Bas van Dijk <v.dijk.bas <at> gmail.com> wrote:

I'm playing a bit with the new ConstraintKinds feature in GHC
7.4.1-rc1. I'm trying to give the Functor class an associated
constraint so that we can make Set an instance of Functor. The
following code works but I wonder if the trick with: class Empty a;
instance Empty a, is the recommended way to do this:

{-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}

import GHC.Prim (Constraint)

import Prelude hiding (Functor, fmap)

import           Data.Set (Set)
import qualified Data.Set as S (map, fromList)

class Functor f where
    type C f :: * -> Constraint
    type C f = Empty

    fmap :: (C f a, C f b) => (a -> b) -> f a -> f b

class Empty a; instance Empty a

instance Functor Set where
    type C Set = Ord
    fmap = S.map

instance Functor [] where
    fmap = map

testList = fmap (+1) [1,2,3]
testSet  = fmap (+1) (S.fromList [1,2,3])

Cheers and thanks for a great new feature!

Bas

 

This is the same solution I wound up with in

 

 

Adding an argument to the family would work but is somewhat unsatisfying as it mucks with polymorphic recursive use of the dictionary, and with placing constraints on constraints, so I prefer to keep as few arguments as possible.

 

You can go farther with Functor by using polymorphic kinds and indexing the source and destination Category as well as the class of objects in the category.

 

I should probably write up what I've done with this, but doing so lets you have real product and coproduct Category instances, which were previously not possible (a fact which in part drove me to write all the semigroupoid code i have on hackage.

 

-Edward

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Edward Kmett | 23 Dec 17:41 2011
Picon

Re: ConstraintKinds and default associated empty constraints

On Fri, Dec 23, 2011 at 10:17 AM, Simon Peyton-Jones <simonpj <at> microsoft.com> wrote:

Right now it seems it is either * or Constraint depending on context. 

 

Correct.  Tuple bracket are used for both types and Constraints, and we have to decide which from context. 


Whew, that agrees with my original understanding. =) 

My attempt at forming a new understanding was driven by your example.

class Functor f where
   type C f :: * -> Constraint
   type C f = ()

such that
 
C :: (* -> *) -> * -> Constraint

In that, you put () in a position where it would have kind * -> Constraint, hence my confusion when you subsequently stated that there was a bug that needed to be fixed. =)

No.  () has kind * or Constraint, depending on context, never a -> Constraint.

Similarly (,) has kind * -> * -> * or Constraint -> Constraint -> Constraint, depending on context.


Imaging that there are two sorts of parens, one for types and one for constraints.  We figure out which is intended from context.


Yep. We have a small compiler here at ClariFi for a very Haskell-like language in which we've implemented pretty much this same scheme.

That said, instead of magically swapping kinds out we instead take the superkind level and introduce subtyping at that level, giving us two superkinds, say, Box and Circle, such that Circle is a sub-superkind of Box and both * and Constraint have superkind Circle.

Then (,) :: forall (a: Circle). a -> a -> a and you don't need to swap kinds on fully saturated tuples, and it can kind check types like '(,) ()' in isolation without issue.

-Edward
_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Simon Peyton-Jones | 23 Dec 17:44 2011
Picon

RE: ConstraintKinds and default associated empty constraints

My attempt at forming a new understanding was driven by your example.

                               

class Functor f where
   type C f :: * -> Constraint
   type C f = ()

 

sorry -- that was simply type incorrect.  () does not have kind *  -> Constraint

 

S

 

From: Edward Kmett [mailto:ekmett <at> gmail.com]
Sent: 23 December 2011 16:41
To: Simon Peyton-Jones
Cc: Bas van Dijk; glasgow-haskell-users <at> haskell.org
Subject: Re: ConstraintKinds and default associated empty constraints

 

On Fri, Dec 23, 2011 at 10:17 AM, Simon Peyton-Jones <simonpj <at> microsoft.com> wrote:

Right now it seems it is either * or Constraint depending on context. 

 

Correct.  Tuple bracket are used for both types and Constraints, and we have to decide which from context. 

 

Whew, that agrees with my original understanding. =) 

 

My attempt at forming a new understanding was driven by your example.

                             

class Functor f where
   type C f :: * -> Constraint
   type C f = ()

 

such that

 

C :: (* -> *) -> * -> Constraint

 

In that, you put () in a position where it would have kind * -> Constraint, hence my confusion when you subsequently stated that there was a bug that needed to be fixed. =)

 

No.  () has kind * or Constraint, depending on context, never a -> Constraint.

Similarly (,) has kind * -> * -> * or Constraint -> Constraint -> Constraint, depending on context.

 

Imaging that there are two sorts of parens, one for types and one for constraints.  We figure out which is intended from context.

 

Yep. We have a small compiler here at ClariFi for a very Haskell-like language in which we've implemented pretty much this same scheme.

 

That said, instead of magically swapping kinds out we instead take the superkind level and introduce subtyping at that level, giving us two superkinds, say, Box and Circle, such that Circle is a sub-superkind of Box and both * and Constraint have superkind Circle.

 

Then (,) :: forall (a: Circle). a -> a -> a and you don't need to swap kinds on fully saturated tuples, and it can kind check types like '(,) ()' in isolation without issue.

 

-Edward

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Bas van Dijk | 8 Jan 14:32 2012
Picon

Re: ConstraintKinds and default associated empty constraints

On 23 December 2011 17:44, Simon Peyton-Jones <simonpj <at> microsoft.com> wrote:
> My attempt at forming a new understanding was driven by your example.
>
> class Functor f where
>    type C f :: * -> Constraint
>    type C f = ()
>
> sorry -- that was simply type incorrect.  () does not have kind *  ->
> Constraint

So am I correct that the `class Empty a; instance Empty a` trick is
currently the only way to get default associated empty constraints?

Will this change in GHC-7.4.1? (For example by having an overloaded `()`)

The reason I ask is I would like to know if it's already feasible to
start proposing adding these associated constraints to Functor,
Applicative and Monad.

Cheers,

Bas

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
wren ng thornton | 9 Jan 06:21 2012

Re: ConstraintKinds and default associated empty constraints

On 1/8/12 8:32 AM, Bas van Dijk wrote:
> On 23 December 2011 17:44, Simon Peyton-Jones<simonpj <at> microsoft.com>  wrote:
>> My attempt at forming a new understanding was driven by your example.
>>
>> class Functor f where
>>     type C f :: * ->  Constraint
>>     type C f = ()
>>
>> sorry -- that was simply type incorrect.  () does not have kind *  ->
>> Constraint
>
> So am I correct that the `class Empty a; instance Empty a` trick is
> currently the only way to get default associated empty constraints?

Couldn't the following work?

     class Functor f where
         type C f :: * -> Constraint
         type C f _ = ()

It seems to me that adding const to the type level (either implicitly or 
explicitly) is cleaner and simpler than overloading () to be Constraint, 
*->Constraint, *->*->Constraint,...

--

-- 
Live well,
~wren
Antoine Latter | 9 Jan 07:30 2012
Picon

Re: ConstraintKinds and default associated empty constraints

On Sun, Jan 8, 2012 at 11:21 PM, wren ng thornton <wren <at> freegeek.org> wrote:
>
>
> Couldn't the following work?
>
>
>    class Functor f where
>        type C f :: * -> Constraint
>        type C f _ = ()
>

I get a parse error from that.

The equivalent:

   class Functor f where
       type FC f :: * -> Constraint
       type FC f a = ()

gives the error:

    Number of parameters must match family declaration; expected 1
    In the type synonym instance default declaration for `FC'
    In the class declaration for `Functor'

> It seems to me that adding const to the type level (either implicitly or
> explicitly) is cleaner and simpler than overloading () to be Constraint,
> *->Constraint, *->*->Constraint,...
>
> --
> Live well,
> ~wren
>
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users <at> haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Antoine Latter | 9 Jan 07:41 2012
Picon

Re: ConstraintKinds and default associated empty constraints

On Mon, Jan 9, 2012 at 12:30 AM, Antoine Latter <aslatter <at> gmail.com> wrote:
> On Sun, Jan 8, 2012 at 11:21 PM, wren ng thornton <wren <at> freegeek.org> wrote:
>>
>>
>> Couldn't the following work?
>>
>>
>>    class Functor f where
>>        type C f :: * -> Constraint
>>        type C f _ = ()
>>
>
> I get a parse error from that.
>
> The equivalent:
>
>   class Functor f where
>       type FC f :: * -> Constraint
>       type FC f a = ()
>

The definitions are accepted by GHC:

   class Functor f where
       type FC f a :: Constraint
       type FC f a = ()

       fmap :: (FC f a, FC f b) => (a -> b) -> f a -> f b

   instance Functor [] where
       fmap = map

But I don't like the 'a' being an index parameter, and then the
following expression:

   fmap (+1) [1::Int]

Gives the error:

    Could not deduce (FC [] Int) arising from a use of `fmap'
    In the expression: fmap (+ 1) [1 :: Int]
    In an equation for `it': it = fmap (+ 1) [1 :: Int]

> gives the error:
>
>    Number of parameters must match family declaration; expected 1
>    In the type synonym instance default declaration for `FC'
>    In the class declaration for `Functor'
>
>> It seems to me that adding const to the type level (either implicitly or
>> explicitly) is cleaner and simpler than overloading () to be Constraint,
>> *->Constraint, *->*->Constraint,...
>>
>> --
>> Live well,
>> ~wren
>>
>>
>> _______________________________________________
>> Glasgow-haskell-users mailing list
>> Glasgow-haskell-users <at> haskell.org
>> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Andres Löh | 9 Jan 08:28 2012

Re: ConstraintKinds and default associated empty constraints

Hi.

> The definitions are accepted by GHC:
>
>   class Functor f where
>       type FC f a :: Constraint
>       type FC f a = ()
>
>       fmap :: (FC f a, FC f b) => (a -> b) -> f a -> f b
>
>   instance Functor [] where
>       fmap = map

Yes. This is what I would have expected to work.

> But I don't like the 'a' being an index parameter, and then the
> following expression:
>
>   fmap (+1) [1::Int]
>
> Gives the error:
>
>    Could not deduce (FC [] Int) arising from a use of `fmap'
>    In the expression: fmap (+ 1) [1 :: Int]
>    In an equation for `it': it = fmap (+ 1) [1 :: Int]
>
>> gives the error:
>>
>>    Number of parameters must match family declaration; expected 1
>>    In the type synonym instance default declaration for `FC'
>>    In the class declaration for `Functor'

I get the same error, but it looks like a bug to me: If I move the
declaration

type FC f a = ()

to the instance, then the example passes.

Cheers,
  Andres
Simon Peyton-Jones | 9 Jan 16:53 2012
Picon

RE: ConstraintKinds and default associated empty constraints

Three things about this ConstraintKinds thread:

First, about 
  class Functor f where
    type C f a :: Constraint
    type C f a = ()
vs
  class Functor f where
    type C f :: * -> Constraint
    type C f = \_ -> ()

I don't know any way of dealing in a decent way with the latter, because it lacks type level lambdas.  GHC
currently allows only the former.  I hope that is enough.  If not, perhaps give an example?

Second, it's true that the former would permit you to *index* on 'a' as well as being parametric in 'a' (which
is probably more what you intend).  That's a deficiency, but it's largely a notational one.  Maybe there
should be some way to specify in a type family definition that some parameters can't be used for indexing. 
It's orthogonal to the question of Constraint kinds, or of defaults for associated types.

Third, () does indeed stand both for the unit tuple and for the empty constraint, depending on context.  So
the code below works fine with HEAD.  I think it's ok with the 7.4 branch too, but it would be safer if someone
would check that.  I included a test for the case tha Antoine found an error with, namely 
	    Could not deduce (FC [] Int) arising from a use of `fmap'

Simon

===================================================================
{-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}
module CK where

import GHC.Prim (Constraint)

import Prelude hiding (Functor, fmap)

import           Data.Set (Set)
import qualified Data.Set as S (map, fromList)

class Functor f where
    type C f a :: Constraint
    type C f a = ()

    fmap :: (C f a, C f b) => (a -> b) -> f a -> f b

instance Functor Set where
    type C Set a = Ord a
    fmap = S.map

instance Functor [] where
    fmap = map

testList = fmap (+1) [1,2,3]
testSet  = fmap (+1) (S.fromList [1,2,3])
test2 = fmap (+1) [1::Int]

| -----Original Message-----
| From: glasgow-haskell-users-bounces <at> haskell.org [mailto:glasgow-haskell-
| users-bounces <at> haskell.org] On Behalf Of Andres Löh
| Sent: 09 January 2012 07:28
| To: Antoine Latter
| Cc: glasgow-haskell-users <at> haskell.org
| Subject: Re: ConstraintKinds and default associated empty constraints
| 
| Hi.
| 
| > The definitions are accepted by GHC:
| >
| >   class Functor f where
| >       type FC f a :: Constraint
| >       type FC f a = ()
| >
| >       fmap :: (FC f a, FC f b) => (a -> b) -> f a -> f b
| >
| >   instance Functor [] where
| >       fmap = map
| 
| Yes. This is what I would have expected to work.
| 
| > But I don't like the 'a' being an index parameter, and then the
| > following expression:
| >
| >   fmap (+1) [1::Int]
| >
| > Gives the error:
| >
| >    Could not deduce (FC [] Int) arising from a use of `fmap'
| >    In the expression: fmap (+ 1) [1 :: Int]
| >    In an equation for `it': it = fmap (+ 1) [1 :: Int]
| >
| >> gives the error:
| >>
| >>    Number of parameters must match family declaration; expected 1
| >>    In the type synonym instance default declaration for `FC'
| >>    In the class declaration for `Functor'
| 
| I get the same error, but it looks like a bug to me: If I move the
| declaration
| 
| type FC f a = ()
| 
| to the instance, then the example passes.
| 
| Cheers,
|   Andres
| 
| _______________________________________________
| Glasgow-haskell-users mailing list
| Glasgow-haskell-users <at> haskell.org
| http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Gábor Lehel | 9 Jan 17:44 2012
Picon

Re: ConstraintKinds and default associated empty constraints

On Mon, Jan 9, 2012 at 4:53 PM, Simon Peyton-Jones
<simonpj <at> microsoft.com> wrote:
> Three things about this ConstraintKinds thread:
>
> First, about
>  class Functor f where
>    type C f a :: Constraint
>    type C f a = ()
> vs
>  class Functor f where
>    type C f :: * -> Constraint
>    type C f = \_ -> ()
>
> I don't know any way of dealing in a decent way with the latter, because it lacks type level lambdas.  GHC
currently allows only the former.  I hope that is enough.  If not, perhaps give an example?
>
>
> Second, it's true that the former would permit you to *index* on 'a' as well as being parametric in 'a'
(which is probably more what you intend).  That's a deficiency, but it's largely a notational one.
 Maybe there should be some way to specify in a type family definition that some parameters can't be used
for indexing.  It's orthogonal to the question of Constraint kinds, or of defaults for associated types.
>
>
> Third, () does indeed stand both for the unit tuple and for the empty constraint, depending on context.
 So the code below works fine with HEAD.  I think it's ok with the 7.4 branch too, but it would be safer if
someone would check that.  I included a test for the case tha Antoine found an error with, namely
>            Could not deduce (FC [] Int) arising from a use of `fmap'
>
> Simon
>
> ===================================================================
> {-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}
> module CK where
>
> import GHC.Prim (Constraint)
>
> import Prelude hiding (Functor, fmap)
>
> import           Data.Set (Set)
> import qualified Data.Set as S (map, fromList)
>
> class Functor f where
>    type C f a :: Constraint
>    type C f a = ()
>
>    fmap :: (C f a, C f b) => (a -> b) -> f a -> f b
>
> instance Functor Set where
>    type C Set a = Ord a
>    fmap = S.map
>
> instance Functor [] where
>    fmap = map
>
> testList = fmap (+1) [1,2,3]
> testSet  = fmap (+1) (S.fromList [1,2,3])
> test2 = fmap (+1) [1::Int]

The problem with this is that you can't write, for example:

type OldFunctor f = (Functor f, forall a. C (f a) ~ ())

(If we had quantified contexts[1], then maybe, but we don't, and it
doesn't seem like it would be even theoretically possible for indexed
constraints without whole program analysis.)

With the other solution, though, you can write:

type OldFunctor f = (Functor f, C f ~ Empty) -- (In the real world I'd
rather call these Functor and Exofunctor...)

Again, I have no problem at all with the Empty class, it's the same
solution I've used. It's even kind polymorphic if you turn that
extension on. The syntax isn't superficially as nice, but it's nice
enough, does the job, and I don't see how you could do better short of
adding type-level lambdas (so you can write type C f = \_ -> ()).

[1] http://hackage.haskell.org/trac/ghc/ticket/2893

>
> | -----Original Message-----
> | From: glasgow-haskell-users-bounces <at> haskell.org [mailto:glasgow-haskell-
> | users-bounces <at> haskell.org] On Behalf Of Andres Löh
> | Sent: 09 January 2012 07:28
> | To: Antoine Latter
> | Cc: glasgow-haskell-users <at> haskell.org
> | Subject: Re: ConstraintKinds and default associated empty constraints
> |
> | Hi.
> |
> | > The definitions are accepted by GHC:
> | >
> | >   class Functor f where
> | >       type FC f a :: Constraint
> | >       type FC f a = ()
> | >
> | >       fmap :: (FC f a, FC f b) => (a -> b) -> f a -> f b
> | >
> | >   instance Functor [] where
> | >       fmap = map
> |
> | Yes. This is what I would have expected to work.
> |
> | > But I don't like the 'a' being an index parameter, and then the
> | > following expression:
> | >
> | >   fmap (+1) [1::Int]
> | >
> | > Gives the error:
> | >
> | >    Could not deduce (FC [] Int) arising from a use of `fmap'
> | >    In the expression: fmap (+ 1) [1 :: Int]
> | >    In an equation for `it': it = fmap (+ 1) [1 :: Int]
> | >
> | >> gives the error:
> | >>
> | >>    Number of parameters must match family declaration; expected 1
> | >>    In the type synonym instance default declaration for `FC'
> | >>    In the class declaration for `Functor'
> |
> | I get the same error, but it looks like a bug to me: If I move the
> | declaration
> |
> | type FC f a = ()
> |
> | to the instance, then the example passes.
> |
> | Cheers,
> |   Andres
> |
> | _______________________________________________
> | Glasgow-haskell-users mailing list
> | Glasgow-haskell-users <at> haskell.org
> | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
>
>
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users <at> haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

--

-- 
Work is punishment for failing to procrastinate effectively.
Nicolas Frisby | 9 Jan 18:00 2012
Picon

Re: ConstraintKinds and default associated empty constraints

Just a note: as section 6 of [1] notes, one way (possibly the only?)
to satisfy a universally quantified constraint would be a suitably
polymorphic instance — i.e. with a type variable in the head. I think
this would mitigate the need for whole program analysis at least in
some cases, including our current Functor example.

On the other hand, the Empty class does nicely avoid this entire
problem for this particular case.

[1] — http://www.haskell.org/haskellwiki/Quantified_contexts

On Mon, Jan 9, 2012 at 10:44 AM, Gábor Lehel <illissius <at> gmail.com> wrote:
> On Mon, Jan 9, 2012 at 4:53 PM, Simon Peyton-Jones
> <simonpj <at> microsoft.com> wrote:
>> Three things about this ConstraintKinds thread:
>>
>> First, about
>>  class Functor f where
>>    type C f a :: Constraint
>>    type C f a = ()
>> vs
>>  class Functor f where
>>    type C f :: * -> Constraint
>>    type C f = \_ -> ()
>>
>> I don't know any way of dealing in a decent way with the latter, because it lacks type level lambdas.  GHC
currently allows only the former.  I hope that is enough.  If not, perhaps give an example?
>>
>>
>> Second, it's true that the former would permit you to *index* on 'a' as well as being parametric in 'a'
(which is probably more what you intend).  That's a deficiency, but it's largely a notational one.
 Maybe there should be some way to specify in a type family definition that some parameters can't be used
for indexing.  It's orthogonal to the question of Constraint kinds, or of defaults for associated types.
>>
>>
>> Third, () does indeed stand both for the unit tuple and for the empty constraint, depending on context.
 So the code below works fine with HEAD.  I think it's ok with the 7.4 branch too, but it would be safer if
someone would check that.  I included a test for the case tha Antoine found an error with, namely
>>            Could not deduce (FC [] Int) arising from a use of `fmap'
>>
>> Simon
>>
>> ===================================================================
>> {-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}
>> module CK where
>>
>> import GHC.Prim (Constraint)
>>
>> import Prelude hiding (Functor, fmap)
>>
>> import           Data.Set (Set)
>> import qualified Data.Set as S (map, fromList)
>>
>> class Functor f where
>>    type C f a :: Constraint
>>    type C f a = ()
>>
>>    fmap :: (C f a, C f b) => (a -> b) -> f a -> f b
>>
>> instance Functor Set where
>>    type C Set a = Ord a
>>    fmap = S.map
>>
>> instance Functor [] where
>>    fmap = map
>>
>> testList = fmap (+1) [1,2,3]
>> testSet  = fmap (+1) (S.fromList [1,2,3])
>> test2 = fmap (+1) [1::Int]
>
> The problem with this is that you can't write, for example:
>
> type OldFunctor f = (Functor f, forall a. C (f a) ~ ())
>
> (If we had quantified contexts[1], then maybe, but we don't, and it
> doesn't seem like it would be even theoretically possible for indexed
> constraints without whole program analysis.)
>
> With the other solution, though, you can write:
>
> type OldFunctor f = (Functor f, C f ~ Empty) -- (In the real world I'd
> rather call these Functor and Exofunctor...)
>
> Again, I have no problem at all with the Empty class, it's the same
> solution I've used. It's even kind polymorphic if you turn that
> extension on. The syntax isn't superficially as nice, but it's nice
> enough, does the job, and I don't see how you could do better short of
> adding type-level lambdas (so you can write type C f = \_ -> ()).
>
> [1] http://hackage.haskell.org/trac/ghc/ticket/2893
>
>
>>
>> | -----Original Message-----
>> | From: glasgow-haskell-users-bounces <at> haskell.org [mailto:glasgow-haskell-
>> | users-bounces <at> haskell.org] On Behalf Of Andres Löh
>> | Sent: 09 January 2012 07:28
>> | To: Antoine Latter
>> | Cc: glasgow-haskell-users <at> haskell.org
>> | Subject: Re: ConstraintKinds and default associated empty constraints
>> |
>> | Hi.
>> |
>> | > The definitions are accepted by GHC:
>> | >
>> | >   class Functor f where
>> | >       type FC f a :: Constraint
>> | >       type FC f a = ()
>> | >
>> | >       fmap :: (FC f a, FC f b) => (a -> b) -> f a -> f b
>> | >
>> | >   instance Functor [] where
>> | >       fmap = map
>> |
>> | Yes. This is what I would have expected to work.
>> |
>> | > But I don't like the 'a' being an index parameter, and then the
>> | > following expression:
>> | >
>> | >   fmap (+1) [1::Int]
>> | >
>> | > Gives the error:
>> | >
>> | >    Could not deduce (FC [] Int) arising from a use of `fmap'
>> | >    In the expression: fmap (+ 1) [1 :: Int]
>> | >    In an equation for `it': it = fmap (+ 1) [1 :: Int]
>> | >
>> | >> gives the error:
>> | >>
>> | >>    Number of parameters must match family declaration; expected 1
>> | >>    In the type synonym instance default declaration for `FC'
>> | >>    In the class declaration for `Functor'
>> |
>> | I get the same error, but it looks like a bug to me: If I move the
>> | declaration
>> |
>> | type FC f a = ()
>> |
>> | to the instance, then the example passes.
>> |
>> | Cheers,
>> |   Andres
>> |
>> | _______________________________________________
>> | Glasgow-haskell-users mailing list
>> | Glasgow-haskell-users <at> haskell.org
>> | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
>>
>>
>>
>> _______________________________________________
>> Glasgow-haskell-users mailing list
>> Glasgow-haskell-users <at> haskell.org
>> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
>
>
>
> --
> Work is punishment for failing to procrastinate effectively.
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users <at> haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Simon Peyton-Jones | 9 Jan 19:04 2012
Picon

RE: ConstraintKinds and default associated empty constraints

| The problem with this is that you can't write, for example:
| 	
| type OldFunctor f = (Functor f, forall a. C (f a) ~ ())
| 
| (If we had quantified contexts[1], then maybe, but we don't, and it
| doesn't seem like it would be even theoretically possible for indexed
| constraints without whole program analysis.)
| 
| With the other solution, though, you can write:
| 
| type OldFunctor f = (Functor f, C f ~ Empty) -- (In the real world I'd
| rather call these Functor and Exofunctor...)

Well, you'll just have to use the Empty class for that situation!

Bottom line: I think we have agreed that what GHC implements is all we can reasonably do for now. Yell if you disagree

Simon

| -----Original Message-----
| From: Gábor Lehel [mailto:illissius <at> gmail.com]
| Sent: 09 January 2012 16:45
| To: Simon Peyton-Jones
| Cc: Andres Löh; Antoine Latter; glasgow-haskell-users <at> haskell.org
| Subject: Re: ConstraintKinds and default associated empty constraints
| 
| On Mon, Jan 9, 2012 at 4:53 PM, Simon Peyton-Jones
| <simonpj <at> microsoft.com> wrote:
| > Three things about this ConstraintKinds thread:
| >
| > First, about
| >  class Functor f where
| >    type C f a :: Constraint
| >    type C f a = ()
| > vs
| >  class Functor f where
| >    type C f :: * -> Constraint
| >    type C f = \_ -> ()
| >
| > I don't know any way of dealing in a decent way with the latter, because it
| lacks type level lambdas.  GHC currently allows only the former.  I hope that
| is enough.  If not, perhaps give an example?
| >
| >
| > Second, it's true that the former would permit you to *index* on 'a' as
| well as being parametric in 'a' (which is probably more what you intend).
|  That's a deficiency, but it's largely a notational one.  Maybe there should
| be some way to specify in a type family definition that some parameters can't
| be used for indexing.  It's orthogonal to the question of Constraint kinds,
| or of defaults for associated types.
| >
| >
| > Third, () does indeed stand both for the unit tuple and for the empty
| constraint, depending on context.  So the code below works fine with HEAD.  I
| think it's ok with the 7.4 branch too, but it would be safer if someone would
| check that.  I included a test for the case tha Antoine found an error with,
| namely
| >            Could not deduce (FC [] Int) arising from a use of `fmap'
| >
| > Simon
| >
| > ===================================================================
| > {-# LANGUAGE ConstraintKinds, TypeFamilies, FlexibleInstances #-}
| > module CK where
| >
| > import GHC.Prim (Constraint)
| >
| > import Prelude hiding (Functor, fmap)
| >
| > import           Data.Set (Set)
| > import qualified Data.Set as S (map, fromList)
| >
| > class Functor f where
| >    type C f a :: Constraint
| >    type C f a = ()
| >
| >    fmap :: (C f a, C f b) => (a -> b) -> f a -> f b
| >
| > instance Functor Set where
| >    type C Set a = Ord a
| >    fmap = S.map
| >
| > instance Functor [] where
| >    fmap = map
| >
| > testList = fmap (+1) [1,2,3]
| > testSet  = fmap (+1) (S.fromList [1,2,3])
| > test2 = fmap (+1) [1::Int]
| 
| The problem with this is that you can't write, for example:
| 	
| type OldFunctor f = (Functor f, forall a. C (f a) ~ ())
| 
| (If we had quantified contexts[1], then maybe, but we don't, and it
| doesn't seem like it would be even theoretically possible for indexed
| constraints without whole program analysis.)
| 
| With the other solution, though, you can write:
| 
| type OldFunctor f = (Functor f, C f ~ Empty) -- (In the real world I'd
| rather call these Functor and Exofunctor...)
| 
| Again, I have no problem at all with the Empty class, it's the same
| solution I've used. It's even kind polymorphic if you turn that
| extension on. The syntax isn't superficially as nice, but it's nice
| enough, does the job, and I don't see how you could do better short of
| adding type-level lambdas (so you can write type C f = \_ -> ()).
| 
| [1] http://hackage.haskell.org/trac/ghc/ticket/2893
| 
| 
| >
| > | -----Original Message-----
| > | From: glasgow-haskell-users-bounces <at> haskell.org [mailto:glasgow-haskell-
| > | users-bounces <at> haskell.org] On Behalf Of Andres Löh
| > | Sent: 09 January 2012 07:28
| > | To: Antoine Latter
| > | Cc: glasgow-haskell-users <at> haskell.org
| > | Subject: Re: ConstraintKinds and default associated empty constraints
| > |
| > | Hi.
| > |
| > | > The definitions are accepted by GHC:
| > | >
| > | >   class Functor f where
| > | >       type FC f a :: Constraint
| > | >       type FC f a = ()
| > | >
| > | >       fmap :: (FC f a, FC f b) => (a -> b) -> f a -> f b
| > | >
| > | >   instance Functor [] where
| > | >       fmap = map
| > |
| > | Yes. This is what I would have expected to work.
| > |
| > | > But I don't like the 'a' being an index parameter, and then the
| > | > following expression:
| > | >
| > | >   fmap (+1) [1::Int]
| > | >
| > | > Gives the error:
| > | >
| > | >    Could not deduce (FC [] Int) arising from a use of `fmap'
| > | >    In the expression: fmap (+ 1) [1 :: Int]
| > | >    In an equation for `it': it = fmap (+ 1) [1 :: Int]
| > | >
| > | >> gives the error:
| > | >>
| > | >>    Number of parameters must match family declaration; expected 1
| > | >>    In the type synonym instance default declaration for `FC'
| > | >>    In the class declaration for `Functor'
| > |
| > | I get the same error, but it looks like a bug to me: If I move the
| > | declaration
| > |
| > | type FC f a = ()
| > |
| > | to the instance, then the example passes.
| > |
| > | Cheers,
| > |   Andres
| > |
| > | _______________________________________________
| > | Glasgow-haskell-users mailing list
| > | Glasgow-haskell-users <at> haskell.org
| > | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
| >
| >
| >
| > _______________________________________________
| > Glasgow-haskell-users mailing list
| > Glasgow-haskell-users <at> haskell.org
| > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
| 
| 
| 
| --
| Work is punishment for failing to procrastinate effectively.
Bas van Dijk | 9 Jan 08:23 2012
Picon

Re: ConstraintKinds and default associated empty constraints

That would be nice. It would also be nice to be able to use _ in type signatures as in:

const :: a -> _ -> a
const x _ = x

During type checking each _ could be replaced by a new unique type variable. Visa versa should also be possible: during type inferencing each unique type variable could be replaced by a _.

Bas

On Jan 9, 2012 6:22 AM, "wren ng thornton" <wren <at> freegeek.org> wrote:
On 1/8/12 8:32 AM, Bas van Dijk wrote:
On 23 December 2011 17:44, Simon Peyton-Jones<simonpj <at> microsoft.com>  wrote:
My attempt at forming a new understanding was driven by your example.

class Functor f where
   type C f :: * ->  Constraint
   type C f = ()

sorry -- that was simply type incorrect.  () does not have kind *  ->
Constraint

So am I correct that the `class Empty a; instance Empty a` trick is
currently the only way to get default associated empty constraints?

Couldn't the following work?

   class Functor f where
       type C f :: * -> Constraint
       type C f _ = ()

It seems to me that adding const to the type level (either implicitly or explicitly) is cleaner and simpler than overloading () to be Constraint, *->Constraint, *->*->Constraint,...

--
Live well,
~wren

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Edward Kmett | 9 Jan 17:21 2012
Picon

Re: ConstraintKinds and default associated empty constraints

On Sun, Jan 8, 2012 at 8:32 AM, Bas van Dijk <v.dijk.bas <at> gmail.com> wrote:
On 23 December 2011 17:44, Simon Peyton-Jones <simonpj <at> microsoft.com> wrote:
> My attempt at forming a new understanding was driven by your example.
>
> class Functor f where
>    type C f :: * -> Constraint
>    type C f = ()
>
> sorry -- that was simply type incorrect.  () does not have kind *  ->
> Constraint

So am I correct that the `class Empty a; instance Empty a` trick is
currently the only way to get default associated empty constraints?

Yes.
_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Gmane