diff --git a/message-index/messages/GHC-43085/index.md b/message-index/messages/GHC-43085/index.md new file mode 100644 index 0000000..938176d --- /dev/null +++ b/message-index/messages/GHC-43085/index.md @@ -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) + | ^^^^^^ +~~~ diff --git a/message-index/messages/GHC-43085/overlapping/after/Overlapping.hs b/message-index/messages/GHC-43085/overlapping/after/Overlapping.hs new file mode 100644 index 0000000..0b1651c --- /dev/null +++ b/message-index/messages/GHC-43085/overlapping/after/Overlapping.hs @@ -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) diff --git a/message-index/messages/GHC-43085/overlapping/before/Overlapping.hs b/message-index/messages/GHC-43085/overlapping/before/Overlapping.hs new file mode 100644 index 0000000..c9987ba --- /dev/null +++ b/message-index/messages/GHC-43085/overlapping/before/Overlapping.hs @@ -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) diff --git a/message-index/messages/GHC-43085/overlapping/index.md b/message-index/messages/GHC-43085/overlapping/index.md new file mode 100644 index 0000000..afd0290 --- /dev/null +++ b/message-index/messages/GHC-43085/overlapping/index.md @@ -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 #-}`.