
On Mon, 2005-06-27 at 22:12 +0200, Mads Lindstrøm wrote:
I had newer seen anybody use "forall a." in function signatures before, and therefore was curious about its effect. This is probably do to my inexperience regarding Haskell.
The "forall a." syntax is not Haskell 98. The universal quantification of type variables is implicit in type signatures for polymorphic functions, so there is no need to write it. Haskell extensions have gone beyond the polymorphism allowed in Haskell 98, and thus have needed to disambiguate different types with explicit quantifiers. Hence, glasgow-exts and hugs -98 allow an explicit forall.
If you omit it, the compiler will decide that test is some arbitrary type (Double, Integer, whatever).
I think John is talking about the monomorphism restriction and defaulting. The use of the forall syntax is orthogonal to this.
Note that test in this example is not a function. OK, I assumed it was, as I thought all functions started with lower case and all modules, classes, and data/type constructors started with upper case. It does not take any variables as input, but that is still a function in my book (but I could be wrong there. I am no mathematician).
This kind of declaration: f = rhs is called a "pattern binding" in Haskell. In contrast to this kind of declaration: g pat1 pat2 ... patn = rhs which is called a function binding. g is always a function, but f might be bound to a constant expression, or it might be bound to a function. Now, for convenience, people might say f and g are functions, even when f is bound to a constant expression. Here's where it gets tricky: pattern bindings can be overloaded (so can function bindings, but they are less tricky). When a pattern binding is overloaded it is as if it has an implicit argument, which corresponds to a type class dictionary (a structure that contains concrete implementations of the classes overloaded functions). In that situation you can imagine that the bound variable is a function whose (only) argument is the dictionary - only you don't pass it in explicitly, the compiler adds it for you. This brings us to the monomorphism restriction, which John was talking about. This rule says that a pattern binding is not allowed to be overloaded unless you supply an explicit type signature that says it is overloaded. I won't go into the justification for this (it is a contentious point, read the Haskell Report if you like). Cheers, Bernie.