[Haskell-cafe] ScopedTypeVariables in let-bindings (not where-bindings!) and bug 4347

Paolo Giarrusso p.giarrusso at gmail.com
Sat May 21 17:07:18 CEST 2011


On Sat, May 21, 2011 at 16:46, Felipe Almeida Lessa
<felipe.lessa at gmail.com> wrote:
> On Sat, May 21, 2011 at 11:17 AM, Paolo G. Giarrusso
> <p.giarrusso at gmail.com> 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.html#pattern-type-sigs
>> 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-extensions.html#pattern-type-sigs

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

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/



More information about the Haskell-Cafe mailing list