The reason you need the typeclass constraint is not in the use of 'f' but rather in the use of propagate and what you pass in to it (foo1/foo2 here). If you leave away the typeclass constraint what you're left with is:

propagate' Bar -> (forall a. a->a) -> Bar

The implementation of this function is the same as before, however your use of propagate' is restricted:
forall a. a->a is a very "strict" type, in fact the only inhabitant of this type is 'id' (and bottom, but disregard that here), which means the only way to call propagate is to pass in 'id'. Try it yourself!

Related note: there is a proof that in fact the only inhabitant of (forall a. a -> a) is 'id' and it is the consequence of the "parametricity" property. It is a very neat result I suggest you look it up!


On 2 December 2013 22:28, TP <paratribulations@free.fr> wrote:
TP wrote:

> propagate :: Bar -> (forall a. (FooClass a) => a->a) -> Bar

In fact, I do not understand why we have to add the typeclass constraint
(FooClass a).
Indeed, there is no mention to foo1 and foo2 functions (members of the
FooClass typeclass) in the code of propagate:

-------
propagate v f = case v of
        Bar1 i     -> Bar1 (f i)
        Exp1 b1 b2 -> Exp1 (propagate b1 f) (propagate b2 f)
        Exp2 b1 b2 -> Exp2 (propagate b1 f) (propagate b2 f)
-------

propagate deals with any function a priori, not only foo1 and foo2. So how
to understand the need for this typeclass constraint?

TP

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe