[Agda] Running the TC monad

Yorick Sijsling yoricksijsling at gmail.com
Sat Feb 6 17:26:56 CET 2016


Hi everyone,

I'm experimenting with the new reflection stuff in 2.5.1. These changes are
quite exciting!

I noticed that all the unquoting operations
(unquote/unquoteDecl/unquoteDef) take a TC ⊤, making it hard to return
results of a computation in this monad. Let's say we want to count the
number of constructors of a datatype:

---
open import Prelude
open import Builtin.Reflection

data Foo : Set where
  foo1 : Foo
  foo2 : Foo

countConstructors : Name → TC Nat
countConstructors dt = length <$> getConstructors dt
---

Now i believe in an ideal situation one would have a way to run this
computation and return the result:

---
-- test-countConstructors : runquote (countConstructors (quote Foo)) ≡ 2
-- test-countConstructors = refl
---

As it turns out, it is possible to abuse the unify function to return
arbitrary results by quoting them to a Term first. So we can define a
function which takes a TC A and gives us a tactic which puts the value in
the hole:

---
runTC : ∀ {a} {A : Set a} → TC A → Tactic
runTC c hole =
  do v ← c
  =| `v ← quoteTC v
  =| unify hole `v

test-countConstructors : unquote (runTC (countConstructors (quote Foo))) ≡ 2
test-countConstructors = refl
---

This is usable, but the notation is awkward. I used the new macro
functionality to clean it up:

---
macro
  countConstructors′ : Name → Tactic
  countConstructors′ dt = runTC (countConstructors dt)

test-countConstructors′ : countConstructors′ Foo ≡ 2
test-countConstructors′ = refl
---

All of this took quite a while for me to figure out, so i thought it was
worth sharing. But i also think this is a complicated solution to something
which should be quite simple. Is this the right way to do it or am i
missing something here?

Would it maybe make sense to have runTC as a built-in, and extend the
macro's to allow result types of something else than TC ⊤ in which case
runTC is used? I imagine something like this would be possible:

---
-- macro
--   countConstructors : Name → TC Nat
--   countConstructors dt = length <$> getConstructors dt

-- test-countConstructors : countConstructors Foo ≡ 2
-- test-countConstructors = refl
---

I would like to hear your opinions on this,

Yorick
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.chalmers.se/pipermail/agda/attachments/20160206/f57bae69/attachment.html


More information about the Agda mailing list