
On Sat, May 21, 2011 at 16:46, Felipe Almeida Lessa
On Sat, May 21, 2011 at 11:17 AM, Paolo G. Giarrusso
wrote: As I said, I'm convinced that the argument of let is a pattern, on which a signature is allowed, and GHC correctly understands that, so that this declaration work: let (id :: Int -> Int) = \x -> x
See both of: http://www.haskell.org/ghc/docs/7.0.3/html/users_guide/other-type-extensions... http://www.haskell.org/onlinereport/decls.html#sect4.4.3.2
Actually, it doesn't work ;-)
Prelude> let (id2 :: Int -> Int) = \x -> x <interactive>:1:5: Illegal signature in pattern: Int -> Int Use -XScopedTypeVariables to permit it
I tried that with -XScopedTypeVariables enabled, I didn't say it because I thought it was implicit, and for conciseness: $ ghci Prelude> :set -XScopedTypeVariables Prelude> let (id :: Int -> Int) = \x -> x Prelude> id 1 1
Patterns can't have types in Haskell 98 [1]. So you actually need to see what the ScopedTypeVariables say about it [2, 3]. The GHC user guide [3] is pretty clear saying that pattern type signatures can't bring new type variables into scope like you want.
Well, the examples don't use forall. The guide states that: "Unlike expression and declaration type signatures, pattern type signatures are not implicitly generalised." And I don't want implicit generalization. Adding "nor can they be explicitly generalized" would already be unambiguous, and extra examples would be nice. The rest of the text might or might not forbid to explicitly introduce type variables with forall, but it doesn't say that. I agree that your interpretation is also plausible, but then I'd like the text to be clarified (and the error message to be fixed as you suggest).
[1] http://www.haskell.org/onlinereport/exps.html#sect3.17.1 [2] http://hackage.haskell.org/trac/haskell-prime/wiki/ScopedTypeVariables [3] http://www.haskell.org/ghc/docs/7.0-latest/html/users_guide/other-type-exten...
To me, this inconsistent behavior is a bug, and surely it is undesirable, because of inconsistency - the programmer needs to have sensible rules, about when let var : type = expr works and when not. Or at least a sensible error message.
The bug seems to be with the error message. But the behaviour looks like what was expressed by the docs. I think you could file a bug about it.
Moreover, the proposed solution not always works. Neither of these work: let f :: x -> x; g :: y -> y; (f, g) = (id, id) let f :: x -> x; g :: y -> y; (f, g) = (f, g)
let (f :: forall a. a -> a, g :: forall a. a -> a) = (f, g) let (f :: forall a. a -> a, g :: forall a. a -> a) = (id, id)
If you wonder why one , the tuple might be returned by another function.
Prelude> let f :: x -> x; g :: y -> y; (f, g) = (id, id) <interactive>:1:40: Couldn't match expected type `forall x. x -> x' against inferred type `a -> a' In the expression: id In the expression: (id, id) In a pattern binding: (f, g) = (id, id) Prelude> :s -XNoMonoPatBinds Prelude> let f :: x -> x; g :: y -> y; (f, g) = (id, id)
See [4].
[4] http://hackage.haskell.org/trac/haskell-prime/wiki/MonomorphicPatternBinding...
I see, thanks. This applies even to explicit foralls, which are ignored instead of giving an error. So even the following line only works with -XNoMonoPatBinds, and I get no complaints about the foralls: let f :: forall x. x -> x; g :: forall y. y -> y; (f, g) = (id, id) I guess, I should report a bug about that. Cheers, -- Paolo Giarrusso - Ph.D. Student http://www.informatik.uni-marburg.de/~pgiarrusso/