
On Sat, May 21, 2011 at 11:17 AM, Paolo G. Giarrusso
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 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. [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... Cheers! =) -- Felipe.