如何使用`splitAt`在Vec上实现`rotate`功能?

时间:2018-03-30 20:44:22

标签: agda

问题

我试图在Vec上实现rotate函数,它将每个元素n位置向左移动,循环播放。我可以使用splitAt来实现该功能。这是一幅草图:

open import Data.Nat
open import Data.Nat.DivMod
open import Data.Fin
open import Data.Vec
open import Relation.Nullary.Decidable
open import Relation.Binary.PropositionalEquality

rotateLeft : {A : Set} -> {w : ℕ} -> {w≢0 : False (w ≟ 0)} -> ℕ -> Vec A w -> Vec A w
rotateLeft {A} {w} n vec =
  let parts = splitAt (toℕ (n mod w)) {n = ?} vec
  in  ?

问题是splitAt需要两个输入mn,因此矢量的大小为m + n。由于此处向量的大小为w,因此我需要找到k k + toℕ (n mod w) = w。我无法找到任何标准功能。最好的方法是什么?

有些可能吗?

如果k = n mod w向我提供了k < w的证明,那么我可以尝试实现一个函数diff : ∀ {k w} -> k < w -> ∃ (λ a : Nat) -> a + k = w,这可能会有所帮助。另一种可能性是仅接收ab作为输入,而不是移位的位和矢量的大小,但我不确定这是最好的接口。

更新

我已实施以下内容:

add-diff : (a : ℕ) -> (b : Fin (suc a)) -> toℕ b + (a ℕ-ℕ b) ≡ a
add-diff zero    zero    = refl
add-diff zero    (suc ())
add-diff (suc a) zero    = refl
add-diff (suc a) (suc b) = cong suc (aaa a b)

现在我只需要∀ {n m} -> n mod m < m

的证明

3 个答案:

答案 0 :(得分:1)

这是我想出的。

open import Data.Vec
open import Data.Nat
open import Data.Nat.DivMod
open import Data.Fin hiding (_+_)
open import Data.Product
open import Relation.Binary.PropositionalEquality
open import Data.Nat.Properties using (+-comm)

difference : ∀ m (n : Fin m) → ∃ λ o → m ≡ toℕ n + o
difference zero ()
difference (suc m) zero = suc m , refl
difference (suc m) (suc n) with difference m n
difference (suc m) (suc n) | o , p1 = o , cong suc p1

rotate-help : ∀ {A : Set} {m} (n : Fin m) → Vec A m → Vec A m
rotate-help {A} {m = m} n vec with difference m n
... | o , p rewrite p with splitAt (toℕ n) vec
... | xs , ys , _ = subst (Vec A) (+-comm o (toℕ n)) (ys ++ xs)

rotate : ∀ {A : Set} {m} (n : ℕ) → Vec A m → Vec A m
rotate {m = zero} n v = v
rotate {m = suc m} n v = rotate-help (n mod suc m) v

答案 1 :(得分:1)

在与IRC的adamse交谈后,我想出了这个:

<form id="contact">

  <label>
  Name
  <input type="text" name="name" id="name" required>
  </label>

  <label>
  Email Address
  <input type="email" name="email" id="email" required>
  </label>

  <button type="submit">Submit</button>

</form>

哪个优于他的实现(部分是因为我还在学习Agda的语法,所以我选择只使用函数),但是有效。我相信现在我应该回归更精致的类型。 (不能够感谢他!)

答案 2 :(得分:1)

对于您的最后一个问题k < w,自k = toℕ (n mod w)起,您可以使用bounded中的Data.Fin.Properties

bounded : ∀ {n} (i : Fin n) → toℕ i ℕ< n