I don't think this fact (as stated by the type of fob
) is actually true. Due to the open world property of type classes, you can violate the fundep with module boundaries.
This is show by the following example. This code has only been tested with GHC 7.10.3 (fundeps were massively broken in older versions - don't know what happens then). Assume that you can indeed implement the following:
module A
(module A
,module Data.Type.Equality
,module Data.Proxy
)where
import Data.Type.Equality
import Data.Proxy
class C a b | a -> b
inj_C :: (C a b, C a b') => Proxy a -> b :~: b'
inj_C = error "oops"
Then a few more modules:
module C where
import A
instance C () Int
testC :: C () b => Int :~: b
testC = inj_C (Proxy :: Proxy ())
and
module B where
import A
instance C () Bool
testB :: C () b => b :~: Bool
testB = inj_C (Proxy :: Proxy ())
and
module D where
import A
import B
import C
oops :: Int :~: Bool
oops = testB
oops_again :: Int :~: Bool
oops_again = testC
Int :~: Bool
is clearly not true, so by contradiction, inj_C
cannot exist.
I believe you can still safely write inj_C
with unsafeCoerce
if you don't export the class C
from the module where it's defined. I've used this technique, and have extensively tried, and not been able to write a contradiction. Not to say it's impossible, but at least very difficult and a rare edge case.
class (F a ~ b) => C a b where type F a
as described in the GHC docs, then it works. But that feels like cheating, because you’re putting an equality constraint in, whereas you’re asking to get one out… – Rumpffob
were to typecheck, what would stop one from then picking differentb
andb'
and derivingInt :~: Bool
? I see one of two possibilities - the context is immediately reduced toC a b, b ~ b'
in which case your function becomes trivial, or the function is rejected, because in order to construct thatRefl
, you must know thatb ~ b'
but the context is invalid already so any assumptions from it are invalid. I guess the context is a contradiction but ghc doesn't detect that, instead just throwing a type error. – Karttikeyaa -> b
forcesb ~ b'
(but, apparently, neglects to tell anyone so). Yes, the function is then trivial; it was just a (nearly) minimal example. – Vehemence