Opened 12 months ago

Closed 12 months ago

Last modified 12 months ago

#7856 closed feature request (invalid)

Wrong error message for unknown Instance

Reported by: bas Owned by:
Priority: normal Milestone:
Component: Compiler (Type checker) Version: 7.6.3
Keywords: Instance Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Incorrect warning at compile-time Difficulty: Unknown
Test Case: typecheck/should_fail/T7856 Blocked By:
Blocking: Related Tickets:

Description

This type-incorrect program gives a wrong error message:

main = tmp "hello"
  where tmp :: String -> IO ()
        tmp = sequence_ lst
        lst = [putStrLn "hi"]

Namely:

    Couldn't match expected type `IO ()' with actual type `()'
    Expected type: String -> IO ()
      Actual type: String -> ()
    In the return type of a call of `sequence_'
    In the expression: sequence_ lst

I would not expect the "actual type" to be "String -> ()", but rather "IO ()". Note: GHC expects that "(->) String" is a monad.

Attachments (1)

wrongError.hs (224 bytes) - added by bas 12 months ago.
The file that produces exactly (and only) the error message in the ticket

Download all attachments as: .zip

Change History (4)

Changed 12 months ago by bas

The file that produces exactly (and only) the error message in the ticket

comment:1 Changed 12 months ago by simonpj

  • Difficulty set to Unknown
  • Milestone set to _|_

Here is what is happening. We typecheck this definition

tmp :: String -> IO ()
tmp = sequence_ lst
  where lst = [putStrLn "hi"]

Remember that sequence_ :: Monad m => [m a] -> m (). So GHC generates two type equalities:

(1)    m () ~ (->) String (IO ())   -- From the return type of (sequence_ lst)
(2)    m a  ~ IO ()                 -- From the argument of _sequence

If GHC solved (2) first (by m:=IO, a:=()), all would be well. But it happens to try to solve (1) first, by decomposing into

(1a)   m ~ (->) String
(1b)   () ~ IO ()

And it is (1b) that is reported as an error. In reporting the error GHC says where it came from, namely from (1), that is unifying m () ~ String -> IO (). But by that time GHC has solved (1b) by m:=(->) String, so the error is reported as a mismatch between String -> () and String -> IO ().

So that's the reason. And I don't see an easy way to improve matters. Maybe we should somehow seek to prioritise (2) over (1), but how?

Nice example.

Simon

comment:2 Changed 12 months ago by monoidal

  • Resolution set to invalid
  • Status changed from new to closed

I would not expect the "actual type" to be "String -> ()", but rather "IO ()".

You do get "IO ()", at least on 7.6.2 and HEAD:

    Couldn't match expected type ‛String -> IO ()’
                with actual type ‛IO ()’
    In the return type of a call of ‛sequence_’
    Probable cause: ‛sequence_’ is applied to too many arguments
    In the expression: sequence_ lst
    In an equation for ‛tmp’: tmp = sequence_ lst

Given tmp :: String -> IO (); tmp = sequence_ lst the error message is clear: sequence_ lst is IO () while the signature is String -> IO ().

I'm closing the ticket, but please reopen if you disagree.

comment:3 Changed 12 months ago by simonpj

  • Test Case set to typecheck/should_fail/T7856
Note: See TracTickets for help on using tickets.