[Haskell-cafe] Having a connection between kind * and kind * -> *

Ivan Lazar Miljenovic ivan.miljenovic at gmail.com
Thu Aug 19 10:06:34 EDT 2010


Neil Brown <nccb2 at kent.ac.uk> writes:

> On 19/08/10 14:26, Ivan Lazar Miljenovic wrote:
>> ,----
>> | -- | Indicates what kind of value may be stored within a type.  Once
>> | --   superclass constraints are available, the @v@ parameter will
>> | --   become an associated type.
>> | class Stores c v | c ->  v
>> |
>> | data family Constraints :: (* ->  *) ->  * ->  *
>> |
>> | class (Stores (c v) v) =>  Suitable c v where
>> |   constraints :: Constraints c v
>> `----
>>
>> This works.  However, what doesn't work is when I try to use these
>> classes to re-define Functor:
>>
>> ,----
>> | class (Stores c v) =>  Mappable c v where
>> |   rigidMap :: (v ->  v) ->  c ->  c
>> |
>> | class (Mappable (c v) v) =>  Functor c where
>> |   fmap :: (Suitable c a, Suitable c b) =>  (a ->  b) ->  c a ->  c b
>> `----
>>    
> I'm no typing expert... but how do you expect the type-checker to be
> able to infer a type for 'v' here?  Even with the fundep from Stores,
> c v' should determine 'v', but what value is the type-checker going to
> pick for 'v'?  It's not mentioned again anywhere else, and it is
> needed in order to pick the Mappable instance.

Oh, duh, I see your point now; maybe I should stop using `c' for both
the instance variable of the kind * classes, as well as the instance
variable of the kind * -> * classes.

> What would you do with the Mappable instance anyway?  You can only use
> it if type 'a' is the same as type 'b' (and then I think *this* is
> type you'd want for 'v'), and I don't see that any of your other
> constraints or machinery can help you to identify when this is the
> case.

I wanted to express that Functor is an extension of Mappable.  Obviously
it's still possible to make any Functor instance an instance of Mappable
as well, but it would be nice state that this should be so explicitly.

It isn't really needed in this case, but I was going to split Foldable
up into two classes (the bit that requires kind * -> *, and the bit that
doesn't).  For example, foldr doesn't actually require kind * -> *, but
it probably makes more sense for something like foldMap to only apply to
values of kind * -> *.

-- 
Ivan Lazar Miljenovic
Ivan.Miljenovic at gmail.com
IvanMiljenovic.wordpress.com


More information about the Haskell-Cafe mailing list