Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#5012 closed bug (invalid)

haskell 98 program does not typecheck when compiled with -XTypeFamilies

Reported by: jcpetruzza Owned by:
Priority: normal Milestone:
Component: Compiler (Type checker) Version: 7.0.2
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: GHC rejects valid program Difficulty:
Test Case: Blocked By:
Blocking: Related Tickets:

Description

Consider the following valid Haskell 98 function:

f x =
  do let apply p r = mapM p (r x)
     a <- apply id     fst
     b <- apply return snd
     return (a ++ b)

It compiles fine with both ghc 6.12.x and ghc 7. However, if I add the -XTypeFamilies flag to ghc 7 it is rejected with:

mono.hs:5:17:
    Occurs check: cannot construct the infinite type: a0 = m0 a0
    Expected type: m0 a0 -> m0 a0
      Actual type: m0 a0 -> m0 (m0 a0)
    In the first argument of `apply', namely `return'
    In a stmt of a 'do' expression: b <- apply return snd

If one adds a type signature, the error message gets more intimidating.

A project of mine uses Type Families in some modules so TypeFamilies? is listed as an extension in cabal's configuration file; therefore, it is being passed to every module. That is how I stumbled upon this problem.

Change History (4)

comment:1 Changed 3 years ago by HolgerReinhardt

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

This is caused by a change in the type-checker in GHC 7: http://hackage.haskell.org/trac/ghc/blog/LetGeneralisationInGhc7

This new behaviour gets triggered by activating Type families. The solution is to give explicit local type signatures:

{-# OPTIONS -XTypeFamilies -XRankNTypes -XScopedTypeVariables #-}


f :: forall a m. Monad m => ([m a], [a]) -> m [a]
f x = do 
    a <- apply id     fst
    b <- apply return snd
    return (a ++ b)
     
 where
    apply :: forall b c. (b -> m c) -> (([m a], [a]) -> [b]) -> m [c]    
    apply p r = mapM p (r x) 

If you don't want to write the type signatures, you can just make "apply" a global function and pass in "x" as a parameter:

f x = do 
    a <- apply x id     fst
    b <- apply x return snd
    return (a ++ b)
     
apply x p r = mapM p (r x)   

comment:2 Changed 3 years ago by simonpj

You can also use -XNoMonoLocalBinds (after the -XTypeFamilies). With high probability it will work just fine; but the flag imposes some compromises on the type checker, which is why it's off by default.

Simon

comment:3 Changed 3 years ago by jcpetruzza

Thanks for the quick feedback!

Incidentally, I did check the docs before opening this ticket. I didn't read it in detail but a fast scan of section 7.7 (Type families) didn't reveal any gotchas of this sort. I didn't find anything also on the wiki article linked from there. A short cautionary note regarding let-generalization (and any other implied extension) when using Type Families might be a good idea!

comment:4 Changed 3 years ago by simonpj

Good point. I've edited the wiki page http://www.haskell.org/haskellwiki/GHC/Type_families to include a link to my blog entry on this questionn http://hackage.haskell.org/trac/ghc/blog/LetGeneralisationInGhc7

Simon

Note: See TracTickets for help on using tickets.