私はこのような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
問題は3番目のケースです。これは、xとyがその時点で必ずしも同じタイプであるとは限らないため、失敗します。という事は承知しています。私自身のコードでは、長い回避策を講じることができますが、Eqを直接定義する方法があるはずだと感じています。私の考えでは、解決策は「MまたはTに到達するまで、Fコンストラクターをドリルスルーし続け、それらが同じコンストラクター(つまり、両方ともMまたは両方のT)であり、同じタイプである場合は、同等性の比較を行う」のようなものですが、私はどうやってそれを書くことができるかわかりません。