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

Felipe Almeida Lessa felipe.lessa at gmail.com
Sat May 21 16:46:51 CEST 2011


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

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

Cheers! =)

-- 
Felipe.



More information about the Haskell-Cafe mailing list