我有一个很像这样的 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
顺便说一句,这种类型的要点是支持:
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 )且类型相同,则进行相等比较”,但我'不知道我怎么能写出来。