haskellinstancetypeclassoverlapbifunctor

Haskell independently deciding to infer Bifunctor for my datatype?


For some reason, GHC seems to be deciding that my datatype (with two type parameters) instantiates Bifunctor for no reason at all.

The funniest thing is that this is only used to tell me that there are overlapping instances of Functor for this datatype because I gave an instantiation of Functor for any Bifunctor (and a particular one for the datatype). But, if I try to do bimap on it, it tells me that there is no instance of Bifunctor.

{-# LANGUAGE FlexibleInstances #-}
module BifunctorError where

import Data.Bifunctor

instance Bifunctor f => Functor (f t) where
    fmap = bimap id

data Provenance p t = Provenance p t

-- Uncomment and try to compile: Overlapping instances ???
--instance Functor (Provenance p) where
--  fmap f (Provenance p x) = Provenance p (f x)

I would expect that, because I have not provided anything to indicate that Provenance instantiates Bifunctor, it would not, and so the instance of Functor derived from Bifunctor should be irrelevant. Is this a bug with FlexibleInstances?


Solution

  • When looking for a matching typeclass instance, GHC only looks at the head, not the conditions. It matches the conditions as a secondary step. So when GHC is looking for a Functor instance, all it sees is

    instance (Don't care) => Functor (f t) where
    instance (Don't care) => Functor (Provenance p) where
    

    And both of those instances match just fine. The (Don't care) bit doesn't even come into play until later. So you have some overlapping instances, and that's a problem.

    You can see a bit more about this in this question. The "solution" is to toy with the GHC extension OverlappingInstances, which is a bit of a rabbit hole in and of itself.