syntactic-sugar.lagda.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. ..
  2. ::
  3. module language.syntactic-sugar where
  4. open import Agda.Primitive
  5. open import Agda.Builtin.Bool
  6. open import Agda.Builtin.Nat
  7. open import Agda.Builtin.List
  8. open import Agda.Builtin.Equality
  9. open import Agda.Builtin.String
  10. _++_ : {A : Set} → List A → List A → List A
  11. [] ++ ys = ys
  12. (x ∷ xs) ++ ys = x ∷ (xs ++ ys)
  13. concatMap : {A B : Set} → (A → List B) → List A → List B
  14. concatMap f [] = []
  15. concatMap f (x ∷ xs) = f x ++ concatMap f xs
  16. data Either (A B : Set) : Set where
  17. left : A → Either A B
  18. right : B → Either A B
  19. record Applicative (F : Set → Set) : Set₁ where
  20. field
  21. pure : ∀ {A} → A → F A
  22. _<*>_ : ∀ {A B} → F (A → B) → F A → F B
  23. open Applicative {{...}}
  24. record Monad (M : Set → Set) : Set₁ where
  25. field
  26. _>>=_ : ∀ {A B} → M A → (A → M B) → M B
  27. overlap {{super}} : Applicative M
  28. open Monad {{...}}
  29. instance
  30. ApplicativeList : Applicative List
  31. pure {{ApplicativeList}} = _∷ []
  32. _<*>_ {{ApplicativeList}} fs xs = concatMap (λ f → concatMap (λ x → f x ∷ []) xs) fs
  33. MonadList : Monad List
  34. _>>=_ {{MonadList}} xs f = concatMap f xs
  35. ApplicativeEither : ∀ {Err} → Applicative (Either Err)
  36. pure {{ApplicativeEither}} = right
  37. _<*>_ {{ApplicativeEither}} (left err) _ = left err
  38. _<*>_ {{ApplicativeEither}} (right f) (left err) = left err
  39. _<*>_ {{ApplicativeEither}} (right f) (right x) = right (f x)
  40. MonadEither : ∀ {Err} → Monad (Either Err)
  41. _>>=_ {{MonadEither}} (left e) f = left e
  42. _>>=_ {{MonadEither}} (right x) f = f x
  43. .. _syntactic-sugar:
  44. ***************
  45. Syntactic Sugar
  46. ***************
  47. .. contents::
  48. :depth: 2
  49. :local:
  50. .. _do-notation:
  51. Do-notation
  52. ===========
  53. A *do-block* consists of the :ref:`layout keyword <lexical-structure-layout>`
  54. ``do`` followed by a sequence of *do-statements*, where
  55. .. code-block:: text
  56. do-stmt ::= pat ← expr [where lam-clauses]
  57. | let decls
  58. | expr
  59. lam-clause ::= pat → expr
  60. The ``where`` clause of a bind is used to handle the cases not matched by the pattern
  61. left of the arrow. See :ref:`details below <do-desugaring>`.
  62. .. note::
  63. Arrows can use either unicode (``←``/``→``) or ASCII (``<-``/``->``) variants.
  64. For example::
  65. filter : {A : Set} → (A → Bool) → List A → List A
  66. filter p xs = do
  67. x ← xs
  68. true ← p x ∷ []
  69. where false → []
  70. x ∷ []
  71. Do-notation is desugared before scope checking and is translated into calls to ``_>>=_`` and ``_>>_``, whatever those happen to be bound in the context of the do-block. This means that do-blocks are not tied to any particular notion of monad. In fact if there are no monadic statements in the do block it can be used as sugar for a ``let``::
  72. pure-do : Nat → Nat
  73. pure-do n = do
  74. let p2 m = m * m
  75. p4 m = p2 (p2 m)
  76. p4 n
  77. check-pure-do : pure-do 5 ≡ 625
  78. check-pure-do = refl
  79. .. _do-desugaring:
  80. Desugaring
  81. ----------
  82. +---------------+----------------------+----------------------+
  83. | Statement | Sugar | Desugars to |
  84. +===============+======================+======================+
  85. | Simple bind | :: | :: |
  86. | | | |
  87. | | do x ← m | m >>= λ x → |
  88. | | m' | m' |
  89. +---------------+----------------------+----------------------+
  90. | Pattern bind | :: | :: |
  91. | | | |
  92. | | do p ← m | m >>= λ where |
  93. | | where pᵢ → mᵢ | p → m' |
  94. | | m' | pᵢ → mᵢ |
  95. +---------------+----------------------+----------------------+
  96. | Absurd match | :: | :: |
  97. | | | |
  98. | | do () ← m | m >>= λ () |
  99. +---------------+----------------------+----------------------+
  100. | Non-binding | :: | :: |
  101. | statement | | |
  102. | | do m | m >> |
  103. | | m' | m' |
  104. +---------------+----------------------+----------------------+
  105. | Let | :: | :: |
  106. | | | |
  107. | | do let ds | let ds in |
  108. | | m' | m' |
  109. +---------------+----------------------+----------------------+
  110. If the pattern in the bind is exhaustive, the where-clause can be omitted.
  111. Example
  112. -------
  113. Do-notation becomes quite powerful together with pattern matching on indexed data. As an example,
  114. let us write a correct-by-construction type checker for simply typed λ-calculus.
  115. First we define the raw terms, using de Bruijn indices for variables and explicit type
  116. annotations on the lambda::
  117. infixr 6 _=>_
  118. data Type : Set where
  119. nat : Type
  120. _=>_ : (A B : Type) → Type
  121. data Raw : Set where
  122. var : (x : Nat) → Raw
  123. lit : (n : Nat) → Raw
  124. suc : Raw
  125. app : (s t : Raw) → Raw
  126. lam : (A : Type) (t : Raw) → Raw
  127. Next up, well-typed terms::
  128. Context = List Type
  129. -- A proof of x ∈ xs is the index into xs where x is located.
  130. infix 2 _∈_
  131. data _∈_ {A : Set} (x : A) : List A → Set where
  132. zero : ∀ {xs} → x ∈ x ∷ xs
  133. suc : ∀ {y xs} → x ∈ xs → x ∈ y ∷ xs
  134. data Term (Γ : Context) : Type → Set where
  135. var : ∀ {A} (x : A ∈ Γ) → Term Γ A
  136. lit : (n : Nat) → Term Γ nat
  137. suc : Term Γ (nat => nat)
  138. app : ∀ {A B} (s : Term Γ (A => B)) (t : Term Γ A) → Term Γ B
  139. lam : ∀ A {B} (t : Term (A ∷ Γ) B) → Term Γ (A => B)
  140. Given a well-typed term we can mechanically erase all the type
  141. information (except the annotation on the lambda) to get the
  142. corresponding raw term::
  143. rawIndex : ∀ {A} {x : A} {xs} → x ∈ xs → Nat
  144. rawIndex zero = zero
  145. rawIndex (suc i) = suc (rawIndex i)
  146. eraseTypes : ∀ {Γ A} → Term Γ A → Raw
  147. eraseTypes (var x) = var (rawIndex x)
  148. eraseTypes (lit n) = lit n
  149. eraseTypes suc = suc
  150. eraseTypes (app s t) = app (eraseTypes s) (eraseTypes t)
  151. eraseTypes (lam A t) = lam A (eraseTypes t)
  152. Now we're ready to write the type checker. The goal is to have a function that takes a
  153. raw term and either fails with a type error, or returns a well-typed term that erases to
  154. the raw term it started with. First, lets define the return type. It's parameterised by
  155. a context and the raw term to be checked::
  156. data WellTyped Γ e : Set where
  157. ok : (A : Type) (t : Term Γ A) → eraseTypes t ≡ e → WellTyped Γ e
  158. We're going to need a corresponding type for variables::
  159. data InScope Γ n : Set where
  160. ok : (A : Type) (i : A ∈ Γ) → rawIndex i ≡ n → InScope Γ n
  161. Lets also have a type synonym for the case when the erasure proof is ``refl``::
  162. infix 2 _ofType_
  163. pattern _ofType_ x A = ok A x refl
  164. Since this is a do-notation example we had better have a monad. Lets use the either
  165. monad with string errors::
  166. TC : Set → Set
  167. TC A = Either String A
  168. typeError : ∀ {A} → String → TC A
  169. typeError = left
  170. For the monad operations, we are using :ref:`instance arguments <instance-arguments>`
  171. to infer which monad is being used.
  172. We are going to need to compare types for equality. This is our first opportunity to take
  173. advantage of pattern matching binds::
  174. _=?=_ : (A B : Type) → TC (A ≡ B)
  175. nat =?= nat = pure refl
  176. nat =?= (_ => _) = typeError "type mismatch: nat ‌≠ _ => _"
  177. (_ => _) =?= nat = typeError "type mismatch: _ => _ ≠ nat"
  178. (A => B) =?= (A₁ => B₁) = do
  179. refl ← A =?= A₁
  180. refl ← B =?= B₁
  181. pure refl
  182. We will also need to look up variables in the context::
  183. lookupVar : ∀ Γ n → TC (InScope Γ n)
  184. lookupVar [] n = typeError "variable out of scope"
  185. lookupVar (A ∷ Γ) zero = pure (zero ofType A)
  186. lookupVar (A ∷ Γ) (suc n) = do
  187. i ofType B ← lookupVar Γ n
  188. pure (suc i ofType B)
  189. Note how the proof obligation that the well-typed deBruijn index erases to
  190. the given raw index is taken care of completely under the hood (in this case
  191. by the ``refl`` pattern in the ``ofType`` synonym).
  192. Finally we are ready to implement the actual type checker::
  193. infer : ∀ Γ e → TC (WellTyped Γ e)
  194. infer Γ (var x) = do
  195. i ofType A ← lookupVar Γ x
  196. pure (var i ofType A)
  197. infer Γ (lit n) = pure (lit n ofType nat)
  198. infer Γ suc = pure (suc ofType nat => nat)
  199. infer Γ (app e e₁) = do
  200. s ofType A => B ← infer Γ e
  201. where _ ofType nat → typeError "numbers cannot be applied to arguments"
  202. t ofType A₁ ← infer Γ e₁
  203. refl ← A =?= A₁
  204. pure (app s t ofType B)
  205. infer Γ (lam A e) = do
  206. t ofType B ← infer (A ∷ Γ) e
  207. pure (lam A t ofType A => B)
  208. In the ``app`` case we use a where-clause to handle the error case when the
  209. function to be applied is well-typed, but does not have a function type.
  210. .. _idiom-brackets:
  211. Idiom brackets
  212. ==============
  213. Idiom brackets is a notation used to make it more convenient to work with applicative
  214. functors, i.e. functors ``F`` equipped with two operations
  215. .. code-block:: agda
  216. pure : ∀ {A} → A → F A
  217. _<*>_ : ∀ {A B} → F (A → B) → F A → F B
  218. As do-notation, idiom brackets desugar before scope checking, so whatever the names ``pure``
  219. and ``_<*>_`` are bound to gets used when desugaring the idiom brackets.
  220. The syntax for idiom brackets is
  221. .. code-block:: agda
  222. (| e a₁ .. aₙ |)
  223. or using unicode lens brackets ``⦇`` (U+2987) and ``⦈`` (U+2988):
  224. .. code-block:: agda
  225. ⦇ e a₁ .. aₙ ⦈
  226. This expands to (assuming left associative ``_<*>_``)
  227. .. code-block:: agda
  228. pure e <*> a₁ <*> .. <*> aₙ
  229. Idiom brackets work well with operators, for instance
  230. .. code-block:: agda
  231. (| if a then b else c |)
  232. desugars to
  233. .. code-block:: agda
  234. pure if_then_else_ <*> a <*> b <*> c
  235. Idiom brackets also support none or multiple applications. If the applicative
  236. functor has an additional binary operation
  237. .. code-block:: agda
  238. _<|>_ : ∀ {A B} → F A → F A → F A
  239. then idiom brackets support multiple applications separated by a vertical bar ``|``, i.e.
  240. .. code-block:: agda
  241. (| e₁ a₁ .. aₙ | e₂ a₁ .. aₘ | .. | eₖ a₁ .. aₗ |)
  242. which expands to (assuming right associative ``_<|>_``)
  243. .. code-block:: agda
  244. (pure e₁ <*> a₁ <*> .. <*> aₙ) <|> ((pure e₂ <*> a₁ <*> .. <*> aₘ) <|> (pure eₖ <*> a₁ <*> .. <*> aₗ))
  245. Idiom brackets without any application ``(|)`` or ``⦇⦈`` expend to ``empty`` if
  246. .. code-block:: agda
  247. empty : ∀ {A} → F A
  248. is in scope. An applicative functor with ``empty`` and ``_<|>_`` is typically
  249. called ``Alternative``.
  250. Note that ``pure``, ``_<*>_``, and ``_<|>_`` need not be in scope to use ``(|)``.
  251. Limitations:
  252. - Binding syntax and operator sections cannot appear immediately inside
  253. idiom brackets.
  254. - The top-level application inside idiom brackets cannot include
  255. implicit applications, so
  256. .. code-block:: agda
  257. (| foo {x = e} a b |)
  258. is illegal. In case the ``e`` is pure you can write
  259. .. code-block:: agda
  260. (| (foo {x = e}) a b |)
  261. which desugars to
  262. .. code-block:: agda
  263. pure (foo {x = e}) <*> a <*> b