3
votes

I have a typeclass with a fundep:

{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}

class C a b | a -> b

I want to provide specific instances:

instance C A B

As well as a general, default instance:

instance C a D

Implementing this code as written, won't compile:

Functional dependencies conflict between instance declarations:
  instance C A B
  instance C a D

Switching to type families is no help:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}

class C a where
  type C' a

instance C A where
  type C' A = B


instance C a where
  type C' a = D
Conflicting family instance declarations:
  C' A = B
  C' a = D

Ideally, I'd like to get GHC to use the OverlappingInstances 'most specific' rule to resolve this.

I understand this is an issue that has been known for a while, with various hacky solutions suggested:

What is the best recommended solution in current GHC Haskell?

1
There is wiki.haskell.org/GHC/AdvancedOverlap which describes what you want, but it's not easy.DenBrahe
Thanks, that's a good reference! It's just a distillation of the hacks mentioned in the links.Ari Fordsham
What about a newtype W a = W a: instance C (W a) ()Iceland_jack
If you flip the argument order of C you can derive instances via W a or AIceland_jack
@Iceland_jack I'd rather not to require wrapping/unwrapping of a newtype.Ari Fordsham

1 Answers

3
votes

The best solution is a closed type family:

type family C' a where
  C' A = B
  C' a = D