
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
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