
in the declaration of Functor: class Functor f where fmap :: (a -> b) -> f a -> f b does the compiler infer that f is a type constructor (not a type) because of the appearance of "f a" and "f b"? What I'm thinking is that some classes are classes of types, not type constructors. Like class CanMakeInt a where makeInt :: a -> Int In this case a is a type, not a type constructor. But there is no difference in the form of the first line of the class declaration. Thanks, Mike

On 07/01/10 18:52, Michael Mossey wrote:
in the declaration of Functor:
class Functor f where fmap :: (a -> b) -> f a -> f b
does the compiler infer that f is a type constructor (not a type) because of the appearance of "f a" and "f b"?
What I'm thinking is that some classes are classes of types, not type constructors. Like
class CanMakeInt a where makeInt :: a -> Int
In this case a is a type, not a type constructor. But there is no difference in the form of the first line of the class declaration.
You are entirely correct! The compiler infers this from the entire class declaration (or maybe it's the entire module). The fact that f is a type-constructor, or a type, or whatever: that's its "kind", and this process the compiler does is called "kind inference". Only rarely can the compiler not figure it out, in which case (per standard) it defaults to * (the 'kind' of ordinary types). (If you use an extension you can also specify kinds explicitly, IIRC, like class Functor (f :: * -> *) where ... )

On Friday 02 July 2010 00:52:47, Michael Mossey wrote:
in the declaration of Functor:
class Functor f where fmap :: (a -> b) -> f a -> f b
does the compiler infer that f is a type constructor (not a type) because of the appearance of "f a" and "f b"?
Yes. The compiler infers the kind of f from the signature of fmap. Specifically, it infers that f must be a unary type constructor of kind (* -> *). * is the kind of types (or nullary type constructors). Since a and b appear as arguments of (->), the compiler infers that a and b both have kind *. Later, f a and f b appear as arguments of (->), so f a and f b also must have kind *, which means that f has kind * -> * (f takes one argument which is a type and produces a type).
What I'm thinking is that some classes are classes of types, not type constructors. Like
class CanMakeInt a where makeInt :: a -> Int
In this case a is a type, not a type constructor. But there is no difference in the form of the first line of the class declaration.
Right. But the compiler takes the methods of the class and their signatures into account, which usually determine the kind of the class parameter (if not, well...). Here, a is an argument of (->), hence a must have kind *, i.e. be a type.
Thanks, Mike
participants (3)
-
Daniel Fischer
-
Isaac Dupree
-
Michael Mossey