最初の試み
この質問を簡潔にするのは難しいですが、最小限の例を提供するために、私がこのタイプを持っていると仮定します。
{-# LANGUAGE GADTs #-}
data Val where
Val :: Eq a => a -> Val
このタイプを使用すると、次の異種のリストを作成できます。
l = [Val 5, Val True, Val "Hello!"]
しかし、残念ながら、インスタンスを書き留めると、問題が発生しEq
ます。
instance Eq Val where
(Val x) == (Val y) = x == y -- type error
ああ、だから私たちはCould not deduce (a1 ~ a)
。まったく正しい。定義には何も書かれておらず、同じタイプx
でなければなりません。y
実際、要点は、それらが異なる可能性を許容することでした。
2回目の試行
Data.Typeable
ミックスに取り入れて、同じタイプの場合にのみ2つを比較してみましょう。
data Val2 where
Val2 :: (Eq a, Typeable a) => a -> Val2
instance Eq Val2 where
(Val2 x) == (Val2 y) = fromMaybe False $ (==) x <$> cast y
これはかなりいいです。x
とy
が同じタイプの場合、基になるEq
インスタンスを使用します。それらが異なる場合は、を返しますFalse
。ただし、このチェックは実行時まで遅延されるため、nonsense = Val2 True == Val2 "Hello"
文句なしにタイプチェックできます。
質問
私はここで依存型をいちゃつくことに気づきましたが、Haskell型システムが実行時に返送nonsense
するようなものを許可しながら、上記のようなものを静的に拒否することは可能ですか?sensible = Val2 True == Val2 False
False
この問題に取り組むほど、必要な操作を型レベルの関数として実装するために、 HListの手法のいくつかを採用する必要があるようです。しかし、私は実存主義とGADTを使用するのは比較的新しいので、これらだけで解決策が見つかるかどうか知りたいです。したがって、答えが「いいえ」の場合は、この問題がこれらの機能の限界に達する正確な場所についての議論と、適切な手法、HListなどへの微調整に感謝します。