NanoLens.agda 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. {-- NanoLens.agda - very basic lens with auto-derivation for records
  2. -- Copyright (C) 2018 caryoscelus
  3. --
  4. -- This program is free software: you can redistribute it and/or modify
  5. -- it under the terms of the GNU General Public License as published by
  6. -- the Free Software Foundation, either version 3 of the License, or
  7. -- (at your option) any later version.
  8. --
  9. -- This program is distributed in the hope that it will be useful,
  10. -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. -- GNU General Public License for more details.
  13. --
  14. -- You should have received a copy of the GNU General Public License
  15. -- along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. --}
  17. open import Data.Empty
  18. open import Data.Unit
  19. open import Data.Nat
  20. open import Data.Nat.Show renaming (show to ℕ-show)
  21. open import Data.List
  22. open import Data.Maybe using
  23. ( Maybe ; just ; nothing )
  24. open import Data.String using (String)
  25. open import Function
  26. import Relation.Binary as Bin
  27. open import Relation.Nullary using (Dec ; yes ; no)
  28. open import Relation.Binary.PropositionalEquality using
  29. ( _≡_ ; refl )
  30. import Reflection as R
  31. record _፦_ {ℓ} (A B : Set ℓ) : Set ℓ where
  32. constructor mkLens
  33. field
  34. get : A → B
  35. set : B → A → A
  36. open _፦_ public
  37. modify : ∀ {ℓ} {A B : Set ℓ} (lens : A ፦ B) (f : B → B) → A → A
  38. modify lens f x = set lens (f (get lens x)) x
  39. infixl 10 _፦⟫_
  40. _፦⟫_ : ∀ {ℓ} {A B C : Set ℓ} → A ፦ B → B ፦ C → A ፦ C
  41. get (f ፦⟫ g) = get g ∘ get f
  42. set (f ፦⟫ g) z x = modify f (set g z) x
  43. private
  44. _>>=_ = R.bindTC
  45. _>>_ : ∀ {ℓ} {A : Set ℓ} → R.TC ⊤ → R.TC A → R.TC A
  46. a >> b = a >>= (λ { tt → b })
  47. pure = R.returnTC
  48. strError : ∀ {ℓ} {A : Set ℓ} → String → R.TC A
  49. strError msg = R.typeError [ R.strErr msg ]
  50. find :
  51. ∀ {ℓ} {A : Set ℓ} {P : A → Set ℓ}
  52. (p : (x : A) → Dec (P x)) (xs : List A)
  53. → Maybe A
  54. find p xs
  55. with filter p xs
  56. ... | [] = nothing
  57. ... | y ∷ _ = just y
  58. find-index :
  59. ∀ {ℓ} {A : Set ℓ} {P : A → Set ℓ}
  60. (p : (x : A) → Dec (P x)) (xs : List A)
  61. → Maybe ℕ
  62. find-index = find-index′ 0
  63. where
  64. find-index′ :
  65. ∀ {ℓ} {A : Set ℓ} {P : A → Set ℓ}
  66. (n : ℕ) (p : (x : A) → Dec (P x)) (xs : List A)
  67. → Maybe ℕ
  68. find-index′ n p [] = nothing
  69. find-index′ n p (x ∷ xs)
  70. with p x
  71. ... | yes _ = just n
  72. ... | no _ = find-index′ (suc n) p xs
  73. -- could be a lens if we'd have a proof list is long enough
  74. mod-at : ∀ {ℓ} {A : Set ℓ} (n : ℕ) (f : A → A) → List A → List A
  75. mod-at n f [] = []
  76. mod-at zero f (x ∷ xs) = f x ∷ xs
  77. mod-at (suc n) f (x ∷ xs) = x ∷ mod-at n f xs
  78. module _ where
  79. open R
  80. autoLens′ :
  81. (skipped : ℕ)
  82. (names : List Name)
  83. (rec-name : Name)
  84. (con-name : Name)
  85. (rec-fields : List (Arg Name)) → TC ⊤
  86. autoLens′ _ [] _ _ [] = pure tt
  87. autoLens′ _ [] _ _ (_ ∷ _) = strError "not enough lens names"
  88. autoLens′ _ (_ ∷ _) _ _ [] = strError "not enough field names"
  89. autoLens′ skipped (lens-name ∷ names) rec c (arg i f-name ∷ fs) = do
  90. declareDef
  91. (arg (arg-info visible relevant) lens-name)
  92. (def (quote _፦_)
  93. ( arg (arg-info visible relevant) (def rec [])
  94. ∷ arg (arg-info visible relevant) unknown
  95. ∷ []))
  96. let
  97. l-pats : List (Arg Pattern)
  98. l-pats = replicate skipped
  99. (arg (arg-info visible relevant) (var "y"))
  100. r-pats : List (Arg Pattern)
  101. r-pats = replicate (length fs)
  102. (arg (arg-info visible relevant) (var "y"))
  103. l-vals : List (Arg Term)
  104. l-vals = applyDownFrom
  105. (λ n → arg (arg-info visible relevant)
  106. (var (n + length fs + 1) []))
  107. skipped
  108. r-vals : List (Arg Term)
  109. r-vals = applyDownFrom
  110. (λ n → arg (arg-info visible relevant)
  111. (var n []))
  112. (length fs)
  113. n-args : ℕ
  114. n-args = skipped + 1 + length fs
  115. defineFun lens-name
  116. [ clause [] (con (quote mkLens)
  117. ( arg (arg-info visible relevant) -- get
  118. (def f-name [])
  119. ∷ arg (arg-info visible relevant) -- set
  120. (lam visible (abs "x"
  121. (pat-lam
  122. [ clause
  123. (arg (arg-info visible relevant)
  124. (con c (l-pats ++ [
  125. arg (arg-info visible irrelevant) (var "old")
  126. ] ++ r-pats)) ∷ [])
  127. -- ⇓⇓⇓
  128. (con c (l-vals ++ [
  129. arg (arg-info visible relevant) (var n-args [])
  130. ] ++ r-vals))
  131. ] [])))
  132. ∷ []))
  133. ]
  134. autoLens′ (suc skipped) names rec c fs
  135. autoLens : (names : List Name) (rec : Name) → TC ⊤
  136. autoLens names rec = do
  137. (record′ c fields) ← getDefinition rec
  138. where other → strError "not a record"
  139. autoLens′ 0 names rec c fields
  140. module _ where
  141. open import Data.Product using (_×_ ; _,_)
  142. getGoodType :
  143. (type : Type)
  144. → TC ((Type → Type) × Name × List (Arg Term) × Type)
  145. getGoodType (pi (arg i (def rec-name rec-args)) (abs _ b)) =
  146. pure (id , rec-name , rec-args , b)
  147. getGoodType (pi (arg i x) (abs n b)) = do
  148. (pre-args , rec-name , rec-args , final) ← getGoodType b
  149. pure (pi (arg i x) ∘ abs n ∘ pre-args , rec-name , rec-args , final)
  150. getGoodType t = typeError $ strErr "Non-function type" ∷ termErr t ∷ []
  151. {-# TERMINATING #-}
  152. mapVars : (ℕ → ℕ) → Term → Term
  153. mapVarsArg : (ℕ → ℕ) → Arg Term → Arg Term
  154. mapVars fn (con c args) = con c (map (mapVarsArg fn) args)
  155. mapVars fn (def f args) = def f (map (mapVarsArg fn) args)
  156. mapVars fn (lam v (abs s x)) = lam v (abs s (mapVars fn x))
  157. mapVars fn (pat-lam cs args) = pat-lam cs (map (mapVarsArg fn) args) -- !
  158. mapVars fn (pi a (abs s x)) =
  159. pi (mapVarsArg fn a) (abs s (mapVars fn x))
  160. mapVars fn (sort s) = sort s
  161. mapVars fn (lit l) = lit l
  162. mapVars fn (meta m args) = meta m (map (mapVarsArg fn) args)
  163. mapVars fn unknown = unknown
  164. mapVars fn (var m args) = var (fn m) (map (mapVarsArg fn) args)
  165. mapVarsArg fn (arg i x) = arg i (mapVars fn x)
  166. bumpVars : ℕ → Term → Term
  167. bumpVars n = mapVars (_+ n)
  168. bumpVarsArg : ℕ → Arg Term → Arg Term
  169. bumpVarsArg n = mapVarsArg (_+ n)
  170. -- this isn't totally safe, though
  171. dropVars : ℕ → Term → Term
  172. dropVars n = mapVars (_∸ n)
  173. make-sett : (field-name : Name) → TC Name
  174. make-sett field-name = do
  175. type ← getType field-name
  176. (pre-arguments , rec-name , rec-args , final) ← getGoodType type
  177. record′ con-name fields ← getDefinition rec-name
  178. where
  179. d → strError "not a record definition"
  180. let
  181. n = length fields
  182. field-names = map (λ { (arg i x) → x}) fields
  183. rel-arg = arg (arg-info visible relevant)
  184. set-type = pre-arguments
  185. (pi (rel-arg (dropVars 1 final)) (abs "y"
  186. (pi (rel-arg (def rec-name (map (bumpVarsArg 1) rec-args))) (abs "x"
  187. (def rec-name (map (bumpVarsArg 2) rec-args))))))
  188. just k ← pure $ find-index (_≟-Name field-name) field-names
  189. where
  190. nothing → typeError $
  191. strErr "Field name not found" ∷ nameErr field-name ∷ []
  192. let
  193. all-args : List (Arg Term)
  194. all-args = mod-at k (λ { (arg i x) → arg i (var n [])}) $ zipWith
  195. (λ { m (arg i x) → arg i (var m [])})
  196. (downFrom n)
  197. fields
  198. all-pats : List (Arg Pattern)
  199. all-pats = map (λ { (arg i x) → arg i (var (showName x))}) fields
  200. set-name ← freshName "set"
  201. declareDef
  202. (arg (arg-info visible relevant) set-name)
  203. set-type
  204. defineFun set-name
  205. [ clause
  206. ( arg (arg-info visible relevant)
  207. (var "y")
  208. ∷ arg (arg-info visible relevant)
  209. (con con-name all-pats)
  210. ∷ [] -- ↓ ↓ ↓
  211. ) (con con-name all-args) ]
  212. pure set-name
  213. make-a-lens : (field-name : Name) → TC Name
  214. make-a-lens field-name = do
  215. set-name ← make-sett field-name
  216. lens-name ← freshName "lens"
  217. declareDef
  218. (arg (arg-info visible relevant) lens-name)
  219. (def (quote _፦_)
  220. ( arg (arg-info visible relevant) unknown
  221. ∷ arg (arg-info visible relevant) unknown
  222. ∷ []))
  223. defineFun lens-name
  224. [ clause [] (con (quote mkLens)
  225. ( arg (arg-info visible relevant) -- get
  226. (def field-name [])
  227. ∷ arg (arg-info visible relevant) -- set
  228. (def set-name [])
  229. ∷ []
  230. ))
  231. ]
  232. pure lens-name
  233. a-lens : (field-name : Name) (hole : Term) → TC ⊤
  234. a-lens field-name hole = do
  235. lens-name ← make-a-lens field-name
  236. unify hole (def lens-name [])
  237. macro
  238. sett : (field-name : Name) (hole : Term) → TC ⊤
  239. sett field-name hole = do
  240. set-name ← make-sett field-name
  241. unify hole (def set-name [])
  242. ፦[_] = a-lens
  243. module _ where
  244. open import Data.Fin
  245. open import Data.Vec
  246. import Data.Vec as V
  247. ፦vec[_] : ∀ {ℓ} {A : Set ℓ} {size : ℕ} → Fin size → Vec A size ፦ A
  248. get ፦vec[ n ] xs = V.lookup xs n
  249. set ፦vec[ n ] x xs = xs [ n ]≔ x
  250. private
  251. just-a-vec : Vec ℕ 3
  252. just-a-vec = 3 V.∷ 5 V.∷ 9 V.∷ []
  253. just-another : Vec ℕ 3
  254. just-another = set ፦vec[ zero ] 13 just-a-vec
  255. just-ok : just-another ≡ 13 V.∷ 5 V.∷ 9 V.∷ []
  256. just-ok = refl
  257. record InnerVec (A : Set) : Set where
  258. field
  259. icount : ℕ
  260. ivec : Vec A icount
  261. open InnerVec
  262. something : InnerVec ℕ
  263. icount something = 2
  264. ivec something = 0 ∷ 1 ∷ []
  265. -- TODO: dependent
  266. -- something′ : InnerVec ℕ
  267. -- something′ = set (፦[ ivec ] ፦⟫ ፦vec[ 0 ]) 3 something
  268. module _ where
  269. private
  270. record SingleNat : Set where
  271. constructor wrapNat
  272. field
  273. wrapped : ℕ
  274. open SingleNat
  275. t : SingleNat
  276. t = sett wrapped 30 (wrapNat 305)
  277. t′ : SingleNat
  278. t′ = set ፦[ wrapped ] 30 (wrapNat 305)
  279. t-ok : t ≡ wrapNat 30
  280. t-ok = refl
  281. t′-ok : t′ ≡ wrapNat 30
  282. t′-ok = refl
  283. record _×_ (A B : Set) : Set where
  284. constructor _,_
  285. field
  286. fst : A
  287. snd : B
  288. open _×_
  289. pts : ℕ × ℕ
  290. pts = 3 , 10
  291. pkk : ℕ × ℕ
  292. pkk = sett fst 12 pts
  293. pkk-ok : pkk ≡ (12 , 10)
  294. pkk-ok = refl
  295. pkk′ : ℕ × ℕ
  296. pkk′ = set ፦[ snd ] 155 pts
  297. pkk′-ok : pkk′ ≡ (3 , 155)
  298. pkk′-ok = refl
  299. private
  300. record SingleNat : Set where
  301. constructor wrapNat
  302. field
  303. wrapped′ : ℕ
  304. unquoteDecl wrapped = autoLens [ wrapped ] (quote SingleNat)
  305. open import Relation.Binary.PropositionalEquality
  306. get-set : ∀ {w n} → (get wrapped ∘ set wrapped n) w ≡ n
  307. get-set = refl
  308. set-get : ∀ {w} → set wrapped (get wrapped w) w ≡ w
  309. set-get = refl
  310. set-set : ∀ {w n n′} →
  311. (set wrapped n ∘ set wrapped n′) w ≡ set wrapped n w
  312. set-set = refl
  313. private
  314. module test-Pair where
  315. record Pair (A B : Set) : Set where
  316. constructor pair
  317. field
  318. a′ : A
  319. b′ : B
  320. ℕ-Pair = Pair ℕ ℕ
  321. -- TODO
  322. -- unquoteDecl aℕ bℕ = autoLens (aℕ ∷ bℕ ∷ []) (quote ℕ-Pair)
  323. -- unquoteDecl a b = autoLens (a ∷ b ∷ []) (quote Pair)