
#16154: -Wredundant-constraints: False positive -------------------------------------+------------------------------------- Reporter: fumieval | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler (Type | Version: 8.6.3 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect | Unknown/Multiple error/warning at compile-time | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Interesting. Consider these three possible type signatures for `id`: {{{ id x = x }}} 1. `id :: forall a. a -> a`: the most general type 2. `id :: Int -> Int`: not the most general type, by any means, but accepted without warnng. 3. `id :: Num a => a -> a`: not the most general type, although more general than `Int -> Int`. Elicits a redundant constraint warning. Arguably, it's odd that (2) is accepted without complaint, whereas (3) elicits a warning. Still, in the case of `id` there is no reason to prefer (3) over (1). But your example shows that it is, in fact, sometimes desirable to have a constraint that is not used (as in `id`). Here is a small contrived example: {{{ -- f :: (a ~ Bool) => a -> Int f :: a -> Int f x = 3 g :: String -> Int g s = f (read s) }}} Here the type of `y` is unconstrained, but we need to know what it is to resolve the Read constraint. If `f :: a -> Int`, there is no way to resolve the ambiguity, so we get {{{ Foo.hs:38:10: error: • Ambiguous type variable ‘a0’ arising from a use of ‘read’ prevents the constraint ‘(Read a0)’ from being solved. }}} But if we give `f` the signature `f :: (a ~ Bool) => a -> Int`,the ambiguity goes away; it is resolved to `Bool`. But instead we get {{{ Foo.hs:33:1: warning: [-Wredundant-constraints] • Redundant constraint: a ~ Bool • In the type signature for: f :: forall a. (a ~ Bool) => a -> Int | 33 | f :: (a ~ Bool) => a -> Int | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ }}} Your example is similar, but a little more complicated. I'm not sure what to say. The constraint ''is'' redundant for `f`'s definition. And yet a less-general (more constrained) type can aid the caller. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/16154#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler