dep.agda 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. {-# OPTIONS --without-K --safe #-}
  2. {-
  3. dependent types make a lot of things possible, including
  4. type-safe arbitrary argument count functions. however, if
  5. what's we're interested in is computation and making sure
  6. that the computation is correct, we don't need to preserve
  7. dependent types in compiled code: we only need to make sure
  8. the runtime code is correct during compile-time. often
  9. this is done via "erasure", that is, ignoring irrelevant
  10. bits of computation. but it is unclear how one is to erase
  11. arbitrary argument function. what if we can find
  12. non-dependent calculation that provably does the same job?
  13. this file is just a start in that direction, exploring how
  14. such a transformation can be done manually, in order to
  15. then find automated solution
  16. -}
  17. module dep where
  18. open import Data.Nat
  19. import Data.List as L
  20. open import Data.List using (List)
  21. import Data.Vec as V
  22. open import Data.Vec using (Vec)
  23. open import Relation.Binary.PropositionalEquality
  24. open import Function.Core
  25. Fn : ℕ → Set
  26. Fn zero = ℕ
  27. Fn (suc n) = ℕ → Fn n
  28. app-n : ∀ {n} → Vec ℕ n → Fn n → ℕ
  29. app-n V.[] x = x
  30. app-n (x V.∷ xs) f = app-n xs (f x)
  31. _<+>_ : ∀ {n} → Fn n → Fn n → Fn n
  32. _<+>_ {zero} x y = x + y
  33. _<+>_ {suc n} f g = λ x → f x <+> g x
  34. const-n : ∀ {n} → ℕ → Fn n
  35. const-n {zero} x = x
  36. const-n {suc n} x = λ _ → const-n x
  37. add-n : ∀ n → Fn n
  38. add-n zero = 0
  39. add-n (suc n) = λ x → const-n x <+> add-n n
  40. sum : List ℕ → ℕ
  41. sum L.[] = 0
  42. sum (x L.∷ xs) = x + sum xs
  43. sum' : List ℕ → ℕ
  44. sum' x = app-n (V.fromList x) (add-n (L.length x))
  45. module _ where
  46. open ≡-Reasoning
  47. app-const-n-eq : ∀ xs {n} → app-n (V.fromList xs) (const-n n) ≡ n
  48. app-const-n-eq L.[] = refl
  49. app-const-n-eq (x L.∷ xs) = app-const-n-eq xs
  50. app-<+>-eq : ∀ {n} {f g : Fn n} xs →
  51. app-n xs (f <+> g) ≡ app-n xs f + app-n xs g
  52. app-<+>-eq V.[] = refl
  53. app-<+>-eq (x V.∷ xs) = app-<+>-eq xs
  54. sum-eq : ∀ x → sum' x ≡ sum x
  55. sum-eq L.[] = refl
  56. sum-eq (x L.∷ xs) = begin
  57. sum' (x L.∷ xs)
  58. ≡⟨ refl ⟩
  59. app-n (V.fromList (x L.∷ xs)) (add-n (L.length (x L.∷ xs)))
  60. ≡⟨ refl ⟩
  61. app-n (V.fromList xs) (const-n x <+> add-n (L.length xs))
  62. ≡⟨ app-<+>-eq (V.fromList xs) ⟩
  63. app-n (V.fromList xs) (const-n x) +
  64. app-n (V.fromList xs) (add-n (L.length xs))
  65. ≡⟨ cong (_+ _) (app-const-n-eq xs) ⟩
  66. x + app-n (V.fromList xs) (add-n (L.length xs))
  67. ≡⟨ cong (x +_) (sum-eq xs) ⟩
  68. x + sum xs ∎