Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,260
    • Issues 4,260
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 402
    • Merge Requests 402
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Security & Compliance
    • Security & Compliance
    • Dependency List
    • License Compliance
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #9242

Closed
Open
Opened Jun 27, 2014 by Simon Peyton Jones@simonpjDeveloper

Implement {-# OVERLAPPABLE #-} and {-# INCOHERENT #-} pragmas

The language extensions -XIncoherentInstances and -XOverlappingInstances (described in the user manual) apply to every instance declaration in the module. Internally, however, GHC records this information on a per-instance-declaration basis.

It would be much better for the programmer to be able to control these matters on a per-instance-declaration basis. Thus:

instance Show a => Show [a] where
  {-# OVERLAPPABLE #-}
  ...

instance Show [Char] where
  ...

We came across the need for this when discussing the Typeable instances. We have a generic instance like this:

instance (Typeable f, Typeable a) => Typeable (f a) where ....

but also want

instance KnownNat n => Typeable (n :: Nat) where ...

If we seek (Typeable (x::Nat)), we should pick the second instance even though in principle you might imagine that x might be instantiated to (f a), for some f and a. But we know that there are no type constructors f of kind blah -> Nat, so this can never happen and it's safe to pick the second instance. So a local {-# INCOHERENT #-} pragma for this particular instance declaration would be very useful to express this fact.

instance KnownNat n => Typeable (n :: Nat) where
  {-# INCOHERENT #-}
  ...

Quite apart from this special case, it's plain better to have per-instance control

  • Rather than a remote per-module flag, the pragma draws attention that this particular instance is incoherent, overlappable or whatever.
  • The current situation almost certainly means that more instances are marked overlapping than are really necessary.

I have some design questions.

  • Where should the pragma appear, syntactically?
   instance {-# OVERLAPPABLE #-} Show a => Show [a] where ...
or 
   instance Show a => Show [a] {-# OVERLAPPABLE #-} where ...
or
   instance Show a => Show [a] where
      {-# OVERLAPPABLE #-}

Remember that SPECIALISE INSTANCE pragmas appear in the third of the above positions, so I mildly favour that.

  • The user manual (link above) allows overlap if either instance is compiled with -XOverlappingInstances (see the rules towards the end of 7.6.3.5). It would be more explicit to have two pragmas, one to say "I can be overlapped" and one to say "I can overlap something else". The rule would then be that "either IX is marked {-# OVERLAPPABLE #-} or IY is marked {-# OVERLAPPING #-}.
Edited Mar 09, 2019 by Simon Peyton Jones
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: ghc/ghc#9242