涉及nat添加的依赖类型

时间:2017-11-04 18:37:32

标签: agda dependent-type

我需要定义两个版本的操作,其定义略有不同。这是一系列涉及Nat指数的成分。

open import Data.Nat

data Hom : ℕ → ℕ → Set where
  id    : (m : ℕ) → Hom m m
  _∘_   : ∀ {m n k} → Hom n k → Hom m n → Hom m k
  p     : (n : ℕ) → Hom (suc n) n

p1 : (m n : ℕ) → Hom (m + n) n
p1 zero n    = id n
p1 (suc m) n = p1 m n ∘ p (m + n)

p2 : (m n : ℕ) → Hom (m + n) n
p2 zero n    = id n
p2 (suc m) n = {!!} -- p n ∘ p2 m (1 + n)

-- Goal: Hom (suc (m + n)) n
-- Have: Hom (m + suc n) n

我想定义p1p2,并能够互换使用它们。这可行吗?

2 个答案:

答案 0 :(得分:4)

您可以使用here描述的技巧,通过p2直接递归(无subst或重写)来定义_+_。看起来像这样:

record Homable (H : ℕ → ℕ → Set) : Set where
  field
    id-able  : (m : ℕ) → H m m
    _∘-able_ : ∀ {m n k} → H n k → H m n → H m k
    p-able   : (n : ℕ) → H (suc n) n

suc-homable : ∀ {H} → Homable H → Homable (λ m n -> H (suc m) (suc n))
suc-homable homable = record
  { id-able  = λ m → id-able (suc m)
  ; _∘-able_ = _∘-able_
  ; p-able   = λ m → p-able (suc m)
  } where open Homable homable

p2-go : ∀ {H} → Homable H → (m : ℕ) → H m 0
p2-go homable  zero   = id-able 0 where
  open Homable homable
p2-go homable (suc m) = p-able 0 ∘-able p2-go (suc-homable homable) m where
  open Homable homable

plus-homable-hom : ∀ k → Homable (λ m n → Hom (m + k) (n + k))
plus-homable-hom k = record
  { id-able  = λ n → id (n + k)
  ; _∘-able_ = _∘_
  ; p-able   = λ n → p (n + k)
  }

p2 : (m n : ℕ) → Hom (m + n) n
p2 m n = p2-go (plus-homable-hom n) m

成本是你需要维护那些有点乏味的Homable记录,但根据我的经验证明这种方式定义的函数的事情比根据subst或更高版本定义的函数更简单_+′_(当然,除非你绝不想强迫_+′_加入_+_。)

答案 1 :(得分:2)

嗯,你提供的值的类型等于洞的类型,但是Agda没有看到这个事实。更正式地说,这两种类型在命题上是平等的,但在判断上并不相同。问题是由索引m + suc n引起的,由于定义了加法,索引suc m + n在命题上但在判断上不等于open import Data.Nat open import Data.Nat.Properties open import Relation.Binary.PropositionalEquality data Hom : ℕ → ℕ → Set where id : (m : ℕ) → Hom m m _∘_ : ∀ {m n k} → Hom n k → Hom m n → Hom m k p : (n : ℕ) → Hom (suc n) n p1 : (m n : ℕ) → Hom (m + n) n p1 zero n = id n p1 (suc m) n = p1 m n ∘ p (m + n) p2 : (m n : ℕ) → Hom (m + n) n p2 zero n = id n p2 (suc m) n = subst (λ k → Hom k n) (+-suc m n) (p n ∘ p2 m (suc n)) 。解决问题的一种方法是手动向Agda解释两种类型相同:

p2 (suc m) n

然而,这种方法并非没有缺点,因为_+′_ : ℕ → ℕ → ℕ zero +′ n = n suc m +′ n = m +′ suc n p2′ : (m n : ℕ) → Hom (m +′ n) n p2′ zero n = id n p2′ (suc m) n = p n ∘ p2′ m (suc n) 现在在判断上不等于你的预期定义,而是上面涉及subst的表达式。

这个问题似乎与你要做的事情有关:IIUC,p1和p2实际上是可证明相等的,但使用不同的递归结构定义。那很好,但是结果类型的索引应该遵循相同的递归结构,即你应该使用不同版本的 + 来定义p2,它以适当的方式递归p2:

p1

然而,这有另一个缺点,即p2′_+_的类型不再在判断上相等(但仍然在命题上相等)。

你可以尝试的另一件事是使用Agda的重写规则来使public class StatusUpdateHook implements Hook { private static final Logger LOGGER = LoggerFactory.getLogger(StatusUpdateHook.class); @Override public boolean hook(HttpServerExchange exchange, RequestContext context, BsonValue args, BsonDocument confArgs) { LOGGER.info("Hook is Called"); return true; } @Override public boolean doesSupportRequests(RequestContext rc) { return true; } } 满足额外的判断平等,但这很危险,因为它可能会打破一些Agda作为逻辑的理想品质。在这种情况下,我怀疑它很好,但我必须检查。

总之,你可以尝试很多东西,但没有一个没有缺点。哪个是您最好的选择取决于您尝试使用它的目的。