Lambda Abstraction

Lambda expressions

Anonymous functions can be defined using a lambda expression \x u:

myFun = \x  x + x -- equivalent: `myFun x = x + x`

You can also use the Unicode symbol λ (type “\lambda” or “\Gl” in the Emacs Agda mode) instead of \ (type “\\” in the Emacs Agda mode).

Lambda expressions can take several arguments and arguments can optionally be annotated with a type. For instance, both expressions below have type (A : Set) A A (the second expression checks against other types as well):

example₁ = \ (A : Set)(x : A)  x
example₂ = \ A x  x

A functions taking n (> 1) arguments is equivalent to a function that takes a single argument and returns another function with n-1 arguments, i.e. functions are curried.

curry : (λ x y  x + y)  (λ x  (λ y  x + y))
curry = refl

All functions in Agda satisfy η-equality: f is (definitionally) equal to λ x f x.

etaFun : myFun  λ x  myFun x
etaFun = refl

In particular, two lambda expressions with the same body up to renaming of the argument(s) are considered equal.

alpha : (λ x  x + 1)  (λ y  y + 1)
alpha = refl

Lambda expressions can take Implicit Arguments and Instance Arguments by adding curly braces (resp. double curly braces) around the argument.

implicit-lambda = λ {A : Set} (x : A)  x

instance-lambda = λ (A : Set) {{monoid-A : Monoid A}}  mempty

Arguments to lambda expressions can also be annotated with any modality.

Pattern lambda

Anonymous pattern matching functions can be defined by a pattern lambda using one of the two following syntaxes:

\ { p11 .. p1n -> e1 ;  ; pm1 .. pmn -> em }

\ where
  p11 .. p1n -> e1
    pm1 .. pmn -> em

(where, as usual, \ and -> can be replaced by λ and ). Note that the where keyword introduces an indented block of clauses; if there is only one clause then it may be used inline.

Examples of pattern lambdas:

and : Bool  Bool  Bool
and = λ { true x  x ; false _  false }

xor : Bool  Bool  Bool
xor = λ { true  true   false
        ; false false  false
        ; _     _      true
        }

eq : Bool  Bool  Bool
eq = λ where
  true  true   true
  false false  true
  _ _  false

myFst : {A : Set} {B : A  Set}  Σ A B  A
myFst = λ { (a , b)  a }

mySnd : {A : Set} {B : A  Set} (p : Σ A B)  B (fst p)
mySnd = λ { (a , b)  b }

swap : {A B : Set}  A × B  B × A
swap = λ where (a , b)  (b , a)

Pattern lambdas can also use Copatterns by using projections in postfix notation.

swap' : {A B : Set}  A × B  B × A
swap' = λ where
  (a , b) .fst  b
  (a , b) .snd  a

It is not allowed to use where and with constructions in pattern lambdas.

Regular pattern lambdas are treated as non-erased function definitions (see :Run-time Irrelevance). One can make a pattern lambda erased by writing @0 or @erased before the lambda:

@0 _ : @0 Set  Set
_ = λ @0 { A  A }

@0 _ : @0 Set  Set
_ = λ @erased where
  A  A

Internal representation of pattern lambdas

Internally pattern lambdas are translated into a function definition of the following form:

extlam p11 .. p1n = e1
…
extlam pm1 .. pmn = em

where extlam is a fresh name. In other words, pattern lambdas are generative. In particular, two pattern lambdas with the same body are not considered equal by Agda (in contrast to regular lambda expressions).

(λ { true  true ; false  false }) ==
(λ { true  true ; false  false })

This type is equivalent to extlam1 extlam2 for some distinct fresh names extlam1 and extlam2, hence cannot be proven with refl.

Absurd lambda

An absurd lambda is a lambda expression that uses an absurd pattern ().

absurd-lambda : 0  1  ⊥
absurd-lambda = λ ()

Unlike general pattern lambdas, absurd lambdas do not require curly braces or the where keyword, although using them is still allowed.

absurd-lambda-curly : 0  1  ⊥
absurd-lambda-curly = λ { () }

absurd-lambda-where : 0  1  ⊥
absurd-lambda-where = λ where ()

It is also allowed to have regular arguments before or after the absurd pattern.

absurd-lambda-list : {A : Set} (x : A) (xs : List A)  x  xs  []  ⊥
absurd-lambda-list = λ x xs ()