Skip to content

Commit

Permalink
Add documentation for GHC-43085 (OverlappingInstances)
Browse files Browse the repository at this point in the history
  • Loading branch information
Qbxs committed Oct 13, 2024
1 parent eaae755 commit 07938cb
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 0 deletions.
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 #-}`.

0 comments on commit 07938cb

Please sign in to comment.