У меня есть GADT, что очень похоже на это:
data In a where
M :: MVar a -> In a
T :: TVar a -> In a
F :: (a -> b) -> In a -> In b
Он обертывает различные входные примитивы, но последний конструктор также допускает экземпляр Functor:
instance Functor In where
fmap f (F g v) = F (f . g) v
fmap f x = F f x
Точка этого типа, BTW, должна поддерживать:
read :: In a -> IO a
read (M v) = takeMVar v
read (T v) = atomically (readTVar v)
read (F f v) = f <$> read v
То, что я хочу сделать, это определить очевидный экземпляр Eq для этого типа, например:
instance Eq (In a) where
(M x) == (M y) = x == y
(T x) == (T y) = x == y
(F _ x) == (F _ y) = x == y
_ == _ = False
Проблема - это третий случай, который терпит неудачу, потому что x и y необязательно имеют один и тот же тип в этой точке. Я это понимаю. В моем собственном коде я могу долго работать, но похоже, что должен быть способ определить Eq напрямую. На мой взгляд, решение похоже на "продолжайте сверление через конструкторы F до тех пор, пока вы не нажмете M или T, тогда, если они будут одним и тем же конструктором (т.е. как M, так и оба T) и того же типа, выполните сравнение равенства", но я Я не знаю, как я мог это написать.