Skip to content

Instantly share code, notes, and snippets.

@shmookey
Created April 19, 2016 04:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shmookey/f87961fa1f6199f04782bccf2e2b7723 to your computer and use it in GitHub Desktop.
Save shmookey/f87961fa1f6199f04782bccf2e2b7723 to your computer and use it in GitHub Desktop.
Overlapping instances
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
-- Let's say our project involves a number of similarly-structured reader monads.
-- Their data types might look like this:
data Conf = Conf {}
data ConfReader a = ConfReader { runConfReader :: Conf -> IO a }
-- Their instances for `Functor`, `Applicative` and `Monad` will be almost identical.
-- We only need to know how to construct and run them:
class SimpleReader m c | m -> c, c -> m where
run :: m a -> (c -> IO a)
make :: (c -> IO a) -> m a
-- So let's start with `Functor`. We need `FlexibleInstances` to use a constraint
-- on an instance, and `UndecidableInstances` to allow `c` in the context but
-- not the head.
instance SimpleReader m c => Functor m where
fmap f ma = make $ \c -> f `fmap` run ma c
-- But somehow this causes overlapping instances for Functor!
-- test.hs:24:30:
-- Overlapping instances for Functor IO arising from a use of ‘fmap’
-- Matching instances:
-- instance Functor IO -- Defined in ‘GHC.Base’
-- instance SimpleReader m c => Functor m -- Defined at test.hs:23:10
-- In the expression: f `fmap` run ma c
-- In the second argument of ‘($)’, namely ‘\ c -> f `fmap` run ma c’
-- In the expression: make $ \ c -> f `fmap` run ma c
main = return ()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment