2

I had to use a lot of extensions to create a safe representation for an embedded language in Haskell. At some point when I introduced mutual functional dependency, the type inference stopped to figure out the correct substitutions for type variables. See the example below:

-- create a bidirectional connection between Unit' and ()
class Connect t r | t -> r, r -> t where
data Unit'
instance Connect Unit' () where

-- define a GADT that has only a MyGADT Unit' instance
data MyGADT t where
  MyGADT :: () -> MyGADT Unit'

class Clas a where
  type RetTyp a :: *
  eval' :: Connect (RetTyp a) r => a -> r

instance Clas (MyGADT t) where
  type RetTyp (MyGADT t) = t
  eval' (MyGADT a) = a -- cannot figure out that "a :: ()"

The interesting thing is that when I used a TypeFamily for Connect it was fine:

class Connect' t where
  type Repr t :: *

instance Connect' Unit' where
  type Repr Unit' = ()

class Clas' a where
  type RetTyp' a :: *
  eval'' :: Connect' (RetTyp a) => a -> (Repr (RetTyp' a))

instance Clas' (MyGADT t) where
  type RetTyp' (MyGADT t) = t
  eval'' (MyGADT a) = a -- ok

What is the difference between the type resolution in the two cases?

Boldizsár Németh
  • 1,847
  • 13
  • 20
  • 1
    Looking at this might help http://stackoverflow.com/questions/12407215/how-type-inference-work-in-presence-of-functional-dependencies – Satvik Oct 10 '13 at 11:03
  • you need another associated type to express that functional dependency: `class (UnRepr (Repr t) ~ t) => Connect' t where type Repr t; type UnRepr r` – aavogt Oct 10 '13 at 14:33

0 Answers0