我目前在我的代码中遇到了类似下面的模式(这是从实际代码中简化而来的,这是一个处理表达式的大型GADT)。
data I = A | B | C | D
type family TC1 (a :: I) :: Constraint where
TC1 'A = ()
TC1 'C = ()
TC1 _ = ('True ~ 'False)
type family TC4 (a :: I) :: Constraint where
TC4 'B = ()
TC4 'C = ()
TC4 'D = ()
TC4 _ = ('True ~ 'False)
data T (t :: I) where
T1 :: (TC1 t) => T t
T2 :: T B
T3 :: T t
T4 :: (TC4 t) => T t
etc
castL :: (Typeable t) => [Maybe t] -> Maybe t
castL l = case catMaybes l of
(x:_) -> Just x
[] -> Nothing
mkT1 :: Typeable a => Maybe (T a)
mkT1 = castL [cast (T1 :: T 'A), cast (T1 :: T 'C)]
几个问题:
('True ~ 'False)
?mkT1
看起来有点hacky但似乎确实有效。有没有更好的方法呢?