[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