У меня есть следующее семейство закрытых типов:
type family IsSpecialSize (n :: Nat) :: Bool where
IsSpecialSize 8 = True
IsSpecialSize 16 = True
IsSpecialSize _ = False
Я хотел бы написать одноэлементного свидетеля и решающее лицо для этого семейства типов:
data SSpecial (n :: Nat) where
SSpecial8 :: SSpecial 8
SSpecial16 :: SSpecial 16
SNotSpecial :: (IsSpecialSize n ~ False) => SSpecial n
class DecideSSpecial (n :: Nat) where
specialSize :: SSpecial n
Особые случаи тривиально, чтобы покрыть:
instance {-# OVERLAPPING #-} DecideSSpecial 8 where
specialSize = SSpecial8
instance {-# OVERLAPPING #-} DecideSSpecial 16 where
specialSize = SSpecial16
Однако у нас возникают проблемы с экземпляром generi c. Мы не можем просто написать
instance {-# OVERLAPPABLE #-} (KnownNat n) => DecideSSpecial n where
specialSize = SNotSpecial
, поскольку нет ничего, что могло бы доказать, что IsSpecialSize n ~ False
. Мы можем попробовать добавить его в контекст последнего экземпляра:
instance {-# OVERLAPPABLE #-} (KnownNat n, IsSpecialSize n ~ False) => DecideSSpecial n where
specialSize = SNotSpecial
, но тогда мы не сможем использовать его абстрагирование над n
; Например, следующее определение не может проверить:
instance forall n. (KnownNat n, DecideSSpecial n) => Num (Unsigned n) where
но я очень хочу этого избежать; в конце концов, морально я должен быть в состоянии сказать, равно ли любое данное KnownNat
8, 16 или ни одному.