Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#5032 closed bug (wontfix)

putting left equation sides in parantheses causes GHC.Prim.Any specialization

Reported by: jeltsch Owned by:
Priority: normal Milestone:
Component: Compiler Version: 6.12.1
Keywords: Cc:
Operating System: Linux Architecture: x86_64 (amd64)
Type of failure: None/Unknown Test Case: typecheck/should_compile/T5032
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


I put this code into a file:

identity : a -> a
(identity) = id

I get this error message:

Inferred type is less polymorphic than expected
  Quantified type variable `a' escapes
In the expression: id
In a pattern binding: (identity) = id

This may be correct, I don’t know.

However, I can also do this:

(identity) = id

GHCi accepts this. If I enter :type identity into GHCi, I get this:

identity :: GHC.Prim.Any -> GHC.Prim.Any

This seems weird, in my opinion.

This is also accepted by GHCi:

(identity) = id
hello      = identity "hello"

Evaluating hello yields "hello", and :type identity yields this:

identity :: [Char] -> [Char]

Change History (7)

comment:1 Changed 6 years ago by igloo

Resolution: wontfix
Status: newclosed

It'll work if you use -XNoMonoPatBinds; see for more details.

Technically it's a bug, as MonoPatBinds isn't standard, but it's a deliberate bug, so I'll close as won't-fix.

comment:2 in reply to:  1 ; Changed 6 years ago by tsuyoshi

Replying to igloo:

Technically it's a bug, as MonoPatBinds isn't standard, but it's a deliberate bug, so I'll close as won't-fix.

I doubt that it is intentional that GHCi decides an unspecified monomorphic type variable to be GHC.Prim.Any.

comment:3 in reply to:  2 ; Changed 6 years ago by batterseapower

Replying to tsuyoshi:

I doubt that it is intentional that GHCi decides an unspecified monomorphic type variable to be GHC.Prim.Any.

I think this is the only reasonable thing that can happen. If you have a type (a -> a) that you need to be monomorphic, by definition you can't use (forall a. a -> a). So you have to instantiate the a with some type - in this case GHC.Prim.Any, which at least makes it clear what is going on.

What were you expecting to happen?

comment:4 in reply to:  3 Changed 6 years ago by tsuyoshi

Replying to batterseapower:

What were you expecting to happen?

I would expect an error or a warning. Another option which seems reasonable is to allow a monomorphic type variable as in the OCaml toplevel.

comment:5 Changed 6 years ago by simonmar

The fix is to implement this ticket: #2357

Could we do this for 7.2.1?

comment:6 Changed 6 years ago by simonpj

commit 49dbe60558deee5ea6cd2c7730b7c591d15559c8

Author: Simon Peyton Jones <>
Date:   Tue Aug 16 10:23:52 2011 +0100

    Major improvement to pattern bindings
    This patch makes a number of related improvements
    a) Implements the Haskell Prime semantics for pattern bindings
       (Trac #2357).  That is, a pattern binding p = e is typed
       just as if it had been written
            t = e
            f = case t of p -> f
            g = case t of p -> g
            ... etc ...
       where f,g are the variables bound by p. In paricular it's
       ok to say
          (f,g) = (\x -> x, \y -> True)
       and f and g will get propertly inferred types
          f :: a -> a
          g :: a -> Int
    b) Eliminates the MonoPatBinds flag altogether.  (For the moment
       it is deprecated and has no effect.)  Pattern bindings are now
       generalised as per (a).  Fixes Trac #2187 and #4940, in the
       way the users wanted!
    c) Improves the OutsideIn algorithm generalisation decision.
       Given a definition without a type signature (implying "infer
       the type"), the published algorithm rule is this:
          - generalise *top-level* functions, and
          - do not generalise *nested* functions
       The new rule is
          - generalise a binding whose free variables have
            Guaranteed Closed Types
          - do not generalise other bindings
       Generally, a top-level let-bound function has a Guaranteed
       Closed Type, and so does a nested function whose free vaiables
       are top-level functions, and so on. (However a top-level
       function that is bitten by the Monomorphism Restriction does
       not have a GCT.)
         f x = let { foo y = y } in ...
       Here 'foo' has no free variables, so it is generalised despite
       being nested.
    d) When inferring a type f :: ty for a definition f = e, check that
       the compiler would accept f :: ty as a type signature for that
       same definition.  The type is rejected precisely when the type
       is ambiguous.
          class Wob a b where
            to :: a -> b
            from :: b -> a
          foo x = [x, to (from x)]
       GHC 7.0 would infer the ambiguous type
          foo :: forall a b. Wob a b => b -> [b]
       but that type would give an error whenever it is called; and
       GHC 7.0 would reject that signature if given by the
       programmer.  The new type checker rejects it up front.
       Similarly, with the advent of type families, ambiguous types are
       easy to write by mistake.  See Trac #1897 and linked tickets for
       many examples.  Eg
          type family F a :: *
          f ::: F a -> Int
          f x = 3
       This is rejected because (F a ~ F b) does not imply a~b.  Previously
       GHC would *infer* the above type for f, but was unable to check it.
       Now even the inferred type is rejected -- correctly.
    The main implemenation mechanism is to generalise the abe_wrap
    field of ABExport (in HsBinds), from [TyVar] to HsWrapper. This
    beautiful generalisation turned out to make everything work nicely
    with minimal programming effort.  All the work was fiddling around
    the edges; the core change was easy!

 compiler/deSugar/DsBinds.lhs        |   62 +++-----
 compiler/deSugar/DsExpr.lhs         |    6 +-
 compiler/hsSyn/HsBinds.lhs          |   28 +++-
 compiler/hsSyn/HsUtils.lhs          |   32 +++--
 compiler/main/DynFlags.hs           |   13 +-
 compiler/rename/RnBinds.lhs         |    6 +-
 compiler/typecheck/TcBinds.lhs      |  282 ++++++++++++++++++++--------------
 compiler/typecheck/TcClassDcl.lhs   |   12 +-
 compiler/typecheck/TcEnv.lhs        |  117 +++++++++------
 compiler/typecheck/TcErrors.lhs     |   32 +++--
 compiler/typecheck/TcHsSyn.lhs      |   14 +-
 compiler/typecheck/TcInstDcls.lhs   |   19 ++-
 compiler/typecheck/TcMType.lhs      |    6 +-
 compiler/typecheck/TcRnDriver.lhs   |   14 +-
 compiler/typecheck/TcRnMonad.lhs    |    2 +-
 compiler/typecheck/TcRnTypes.lhs    |   11 +-
 compiler/typecheck/TcSimplify.lhs   |   57 +++++---
 compiler/typecheck/TcTyClsDecls.lhs |    4 +-
 compiler/typecheck/TcType.lhs       |   28 ++--
 19 files changed, 439 insertions(+), 306 deletions(-)

comment:7 Changed 6 years ago by simonpj

Test Case: typecheck/should_compile/T5032

I've fixed this as part of (a) above; see #2357.


Note: See TracTickets for help on using tickets.