NanoLens.agda 12 KB

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