literal-overloading.lagda.rst 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. ..
  2. ::
  3. module language.literal-overloading where
  4. open import Agda.Builtin.Nat
  5. open import Agda.Primitive
  6. open import Agda.Builtin.Bool
  7. open import Agda.Builtin.String
  8. data ⊥ : Set where
  9. record ⊤ : Set where
  10. instance constructor tt
  11. data Fin : Nat → Set where
  12. zero : ∀ {n} → Fin (suc n)
  13. suc : ∀ {n} → Fin n → Fin (suc n)
  14. .. _literal-overloading:
  15. *******************
  16. Literal Overloading
  17. *******************
  18. .. _overloaded-nats:
  19. Natural numbers
  20. ---------------
  21. By default :ref:`natural number literals <lexical-structure-int-literals>` are
  22. mapped to the :ref:`built-in natural number type <built-in-nat>`. This can be
  23. changed with the ``FROMNAT`` built-in, which binds to a function accepting a
  24. natural number:
  25. .. code-block:: agda
  26. {-# BUILTIN FROMNAT fromNat #-}
  27. This causes natural number literals ``n`` to be desugared to ``fromNat n``,
  28. whenever ``fromNat`` is in scope *unqualified* (renamed or not).
  29. Note that the desugaring happens before :ref:`implicit argument
  30. <implicit-arguments>` are inserted so ``fromNat`` can have any number of
  31. implicit or :ref:`instance arguments <instance-arguments>`. This can be
  32. exploited to support overloaded literals by defining a :ref:`type class
  33. <instance-arguments>` containing ``fromNat``::
  34. module number-simple where
  35. record Number {a} (A : Set a) : Set a where
  36. field fromNat : Nat → A
  37. open Number {{...}} public
  38. .. code-block:: agda
  39. {-# BUILTIN FROMNAT fromNat #-}
  40. This definition requires that any natural number can be mapped into the given
  41. type, so it won't work for types like ``Fin n``. This can be solved by refining
  42. the ``Number`` class with an additional constraint::
  43. record Number {a} (A : Set a) : Set (lsuc a) where
  44. field
  45. Constraint : Nat → Set a
  46. fromNat : (n : Nat) {{_ : Constraint n}} → A
  47. open Number {{...}} public using (fromNat)
  48. {-# BUILTIN FROMNAT fromNat #-}
  49. This is the definition used in ``Agda.Builtin.FromNat``.
  50. A ``Number`` instance for ``Nat`` is simply this::
  51. instance
  52. NumNat : Number Nat
  53. NumNat .Number.Constraint _ = ⊤
  54. NumNat .Number.fromNat m = m
  55. A ``Number`` instance for ``Fin n`` can be defined as follows::
  56. _≤_ : (m n : Nat) → Set
  57. zero ≤ n = ⊤
  58. suc m ≤ zero = ⊥
  59. suc m ≤ suc n = m ≤ n
  60. fromN≤ : ∀ m n → m ≤ n → Fin (suc n)
  61. fromN≤ zero _ _ = zero
  62. fromN≤ (suc _) zero ()
  63. fromN≤ (suc m) (suc n) p = suc (fromN≤ m n p)
  64. instance
  65. NumFin : ∀ {n} → Number (Fin (suc n))
  66. NumFin {n} .Number.Constraint m = m ≤ n
  67. NumFin {n} .Number.fromNat m {{m≤n}} = fromN≤ m n m≤n
  68. test : Fin 5
  69. test = 3
  70. It is important that the constraint for literals is trivial. Here,
  71. ``3 ≤ 5`` evaluates to ``⊤`` whose inhabitant is found by unification.
  72. Using predefined function from the standard library and instance ``NumNat``,
  73. the ``NumFin`` instance can be simply:
  74. .. code-block:: agda
  75. open import Data.Fin using (Fin; #_)
  76. open import Data.Nat using (suc; _≤?_)
  77. open import Relation.Nullary.Decidable using (True)
  78. instance
  79. NumFin : ∀ {n} → Number (Fin n)
  80. NumFin {n} .Number.Constraint m = True (suc m ≤? n)
  81. NumFin {n} .Number.fromNat m {{m<n}} = #_ m {m<n = m<n}
  82. .. _agda-prelude: https://github.com/UlfNorell/agda-prelude
  83. .. _overloaded-negative-numbers:
  84. Negative numbers
  85. ----------------
  86. Negative integer literals have no default mapping and can only be used through
  87. the ``FROMNEG`` built-in. Binding this to a function ``fromNeg`` causes
  88. negative integer literals ``-n`` to be desugared to ``fromNeg n``, where ``n``
  89. is a :ref:`built-in natural number <built-in-nat>`. From ``Agda.Builtin.FromNeg``::
  90. record Negative {a} (A : Set a) : Set (lsuc a) where
  91. field
  92. Constraint : Nat → Set a
  93. fromNeg : (n : Nat) {{_ : Constraint n}} → A
  94. open Negative {{...}} public using (fromNeg)
  95. {-# BUILTIN FROMNEG fromNeg #-}
  96. .. _overloaded-strings:
  97. Strings
  98. -------
  99. :ref:`String literals <lexical-structure-string-literals>` are overloaded with
  100. the ``FROMSTRING`` built-in, which works just like ``FROMNAT``. If it is not
  101. bound string literals map to :ref:`built-in strings <built-in-string>`. From
  102. ``Agda.Builtin.FromString``::
  103. record IsString {a} (A : Set a) : Set (lsuc a) where
  104. field
  105. Constraint : String → Set a
  106. fromString : (s : String) {{_ : Constraint s}} → A
  107. open IsString {{...}} public using (fromString)
  108. {-# BUILTIN FROMSTRING fromString #-}
  109. Restrictions
  110. ------------
  111. Currently only integer and string literals can be overloaded.
  112. Overloading does not work in patterns yet.