Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation for GHC-43085 (OverlappingInstances) #546

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions message-index/messages/GHC-43085/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: Overlapping Instances
summary: Multiple type class instances are resolved for a single type class method call.
severity: error
introduced: 9.6.1
---

Type class methods that make use of
[overlapping instances](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/instances.html#overlapping-instances)
lead may lead to an error because the resolved candidates would lead to indeterministic program behavior.

We can solve this by annotating the instances with the `{-# OVERLAPS #-}`, `{-# OVERLAPPING #-}`, `{-# OVERLAPPABLE #-}` and `{-# INCOHERENT #-}` pragma.
The former three can only be used if instances are *strictly more specific* than one another, i.e. the type of an instance can be substituted for the type of another instance.

Note that `{-# INCOHERENT #-}` still leads to indeterministic behavior and thus should be used with caution.

~~~
before/Overlapping.hs:18:19: error: [GHC-43085]
• Overlapping instances for Formatter (Maybe Int)
arising from a use of ‘format’
Matching instances:
instance Formatter (Maybe Int)
-- Defined at before/Overlapping.hs:13:10
instance Formatter a => Formatter (Maybe a)
-- Defined at before/Overlapping.hs:9:10
• In the second argument of ‘($)’, namely
‘format (Nothing :: Maybe Int)’
In the expression: putStrLn $ format (Nothing :: Maybe Int)
In an equation for ‘main’:
main = putStrLn $ format (Nothing :: Maybe Int)
|
18 | main = putStrLn $ format (Nothing :: Maybe Int)
| ^^^^^^
~~~
18 changes: 18 additions & 0 deletions message-index/messages/GHC-43085/overlapping/after/Overlapping.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Overlapping where

class Formatter a where
format :: a -> String

instance Formatter Int where
format = show

instance {-# OVERLAPPABLE #-} (Formatter a) => Formatter (Maybe a) where
format (Just x) = format x
format Nothing = ""

instance {-# OVERLAPS #-} Formatter (Maybe Int) where
format (Just x) = format x
format Nothing = "NaN"

main :: IO ()
main = putStrLn $ format (Nothing :: Maybe Int)
18 changes: 18 additions & 0 deletions message-index/messages/GHC-43085/overlapping/before/Overlapping.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Overlapping where

class Formatter a where
format :: a -> String

instance Formatter Int where
format = show

instance (Formatter a) => Formatter (Maybe a) where
format (Just x) = format x
format Nothing = ""

instance Formatter (Maybe Int) where
format (Just x) = format x
format Nothing = "NaN"

main :: IO ()
main = putStrLn $ format (Nothing :: Maybe Int)
6 changes: 6 additions & 0 deletions message-index/messages/GHC-43085/overlapping/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Overlapping instances for Maybe
---

Here, the two instances `Formatter (Maybe a)` and `Formatter (Maybe Int)` are overlapping.
Since the latter is more specific, we can solve this by annotating the instances with the `{-# OVERLAPPABLE #-}` and `{-# OVERLAPS #-}`.