Ответ 1
Если у вас уже есть b : Bool
, вы можете включить его в предложение: So b
, что немного короче, чем b ≡ true
. Иногда (я не помню никакого реального случая) нет необходимости беспокоиться о правильном типе данных, и этого быстрого решения достаточно.
So
, по-видимому, имеет серьезные недостатки по сравнению с "правильным" term-term: соответствие шаблонов наoh
не дает вам никакой информации с помощью которого вы можете сделать еще один тип проверки типа. В качестве следствия, ЗначенияSo
не могут с пользой участвовать в интерактивной проверке. Сравните это с вычислительной полезностьюDisjoint
, которая представляется в виде списка доказательств того, что каждый столбец вs'
не появляются вs
.
So
дает вам ту же информацию, что и Disjoint
- вам просто нужно извлечь ее. В принципе, если между Disjoint
и Disjoint
нет несогласованности, тогда вы должны иметь возможность написать функцию So (disjoint s) -> Disjoint s
с помощью устранения совпадения шаблонов, рекурсии и невозможности исключения.
Однако, если вы немного измените определение:
So : Bool -> Set
So true = ⊤
So false = ⊥
So
становится действительно полезным типом данных, потому что x : So true
сразу сводится к tt
из-за eta-правила для ⊤
. Это позволяет использовать So
как ограничение: в псевдо-Haskell мы могли бы написать
forall n. (n <=? 3) => Vec A n
и если n
находится в канонической форме (т.е. suc (suc (suc ... zero))
), то n <=? 3
может быть проверен компилятором и никаких доказательств не требуется. В действительности Агда это
∀ {n} {_ : n <=? 3} -> Vec A n
Я использовал этот трюк в ответе this (там {_ : False (m ≟ 0)}
). И я думаю, что без этого простого определения невозможно было бы написать полезную версию машины :
Is-just : ∀ {α} {A : Set α} -> Maybe A -> Set
Is-just = T ∘ isJust
где T
- So
в стандартной библиотеке Agda.
Кроме того, при наличии аргументов экземпляра So
-as-a-data-type может использоваться как So
-as-a-constraint:
open import Data.Bool.Base
open import Data.Nat.Base
open import Data.Vec
data So : Bool -> Set where
oh : So true
instance
oh-instance : So true
oh-instance = oh
_<=_ : ℕ -> ℕ -> Bool
0 <= m = true
suc n <= 0 = false
suc n <= suc m = n <= m
vec : ∀ {n} {{_ : So (n <= 3)}} -> Vec ℕ n
vec = replicate 0
ok : Vec ℕ 2
ok = vec
fail : Vec ℕ 4
fail = vec