Simplifying an instance context makes a rewrite rule no longer typecheck
This code (taken from the reducers
package) compiles:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Prelude (Applicative(..), Functor(..), (.))
class Semigroup m where
(<>) :: m -> m -> m
class Semigroup m => Reducer c m where
snoc :: m -> c -> m
newtype Traversal f = Traversal { getTraversal :: f () }
instance Applicative f => Semigroup (Traversal f) where
Traversal a <> Traversal b = Traversal (a *> b)
instance Applicative f => Reducer (f a) (Traversal f) where
Traversal a `snoc` b = Traversal (() <$ (a *> b))
snocTraversal :: Reducer (f ()) (Traversal f) => Traversal f -> f () -> Traversal f
snocTraversal a = (<>) a . Traversal
{-# RULES "snocTraversal" snoc = snocTraversal #-}
But on GHC 8.2.1 and later, it gives this warning:
GHCi, version 8.2.1: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/rgscott/.ghci
[1 of 1] Compiling Main ( Bug.hs, interpreted )
Bug.hs:21:18: warning: [-Wsimplifiable-class-constraints]
• The constraint ‘Reducer (f ()) (Traversal f)’
matches an instance declaration
instance Applicative f => Reducer (f a) (Traversal f)
-- Defined at Bug.hs:18:10
This makes type inference for inner bindings fragile;
either use MonoLocalBinds, or simplify it using the instance
• In the type signature:
snocTraversal :: Reducer (f ()) (Traversal f) =>
Traversal f -> f () -> Traversal f
|
21 | snocTraversal :: Reducer (f ()) (Traversal f) => Traversal f -> f () -> Traversal f
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I decided to follow GHC's orders and reduce the Reducer (f ()) (Traversal f)
context to just Applicative f
:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import Prelude (Applicative(..), Functor(..), (.))
class Semigroup m where
(<>) :: m -> m -> m
class Semigroup m => Reducer c m where
snoc :: m -> c -> m
newtype Traversal f = Traversal { getTraversal :: f () }
instance Applicative f => Semigroup (Traversal f) where
Traversal a <> Traversal b = Traversal (a *> b)
instance Applicative f => Reducer (f a) (Traversal f) where
Traversal a `snoc` b = Traversal (() <$ (a *> b))
snocTraversal :: Applicative f => Traversal f -> f () -> Traversal f
snocTraversal a = (<>) a . Traversal
{-# RULES "snocTraversal" snoc = snocTraversal #-}
But after doing so, the file no longer typechecks!
GHCi, version 8.2.1: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/rgscott/.ghci
[1 of 1] Compiling Main ( Bug.hs, interpreted )
Bug.hs:23:34: error:
• Could not deduce (Applicative f)
arising from a use of ‘snocTraversal’
from the context: Reducer (f ()) (Traversal f)
bound by the RULE "snocTraversal" at Bug.hs:23:11-46
Possible fix:
add (Applicative f) to the context of the RULE "snocTraversal"
• In the expression: snocTraversal
When checking the transformation rule "snocTraversal"
|
23 | {-# RULES "snocTraversal" snoc = snocTraversal #-}
| ^^^^^^^^^^^^^
Trac metadata
Trac field | Value |
---|---|
Version | 8.2.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler (Type checker) |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |