Скажем, у меня
data Fruit = Apple | Banana | Grape | Orange | Lemon | {- many others -}
и предикат этого типа,
data WineStock : Fruit -> Type where
CanonicalWine : WineStock Grape
CiderIsWineToo : WineStock Apple
который не выполняется для Banana
, Orange
, Lemon
и других.
Это можно сказать, что это определяет WineStock
как предикат на Fruit
; WineStock Grape
истинно (поскольку мы можем построить значение/доказательство этого типа: CanonicalWine
), а также WineStock Apple
, но WineStock Banana
является ложным, поскольку этот тип не заселен никакими значениями/доказательствами.
Затем, как я могу эффективно использовать Not (WineStock Banana)
, Not (WineStock Lemon)
и т.д.? Кажется, что для каждого конструктора Fruit
, кроме Grape
и Apple
, я не могу не кодировать разбиение на случай WineStock
, где-то полное impossible
s:
instance Uninhabited (WineStock Banana) where
uninhabited CanonicalWine impossible
uninhabited CiderIsWineToo impossible
instance Uninhabited (WineStock Lemon) where
uninhabited CanonicalWine impossible
uninhabited CiderIsWineToo impossible
instance Uninhabited (WineStock Orange) where
uninhabited CanonicalWine impossible
uninhabited CiderIsWineToo impossible
Обратите внимание, что:
- код повторяется,
- LoC будет взрываться, когда определение предиката будет расти, получив больше конструкторов. Представьте себе доказательство
Not (Sweet Lemon)
, предполагая, что в определенииFruit
есть много сладких альтернатив.
Таким образом, этот способ не совсем кажется удовлетворительным, почти непрактичным.
Есть ли более элегантные подходы?