Мне пришлось использовать множество расширений, чтобы создать безопасное представление встроенного языка в Haskell. В какой-то момент, когда я ввел взаимную функциональную зависимость, вывод типа остановился, чтобы выяснить правильные замены для переменных типа. См. пример ниже:
-- 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 :: ()"
Интересно то, что когда я использовал TypeFamily для Connect
, все было в порядке:
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
В чем разница между разрешением типа в двух случаях?
class (UnRepr (Repr t) ~ t) => Connect' t where type Repr t; type UnRepr r
- person aavogt   schedule 10.10.2013