Agda-2.3.2.2: test/succeed/Lambda.agda
{-# OPTIONS --no-termination-check #-}
module Lambda where
module Prelude where
data Bool : Set where
true : Bool
false : Bool
if_then_else_ : {A : Set} -> Bool -> A -> A -> A
if true then x else y = x
if false then x else y = y
_∧_ : Bool -> Bool -> Bool
true ∧ y = y
false ∧ y = false
_∨_ : Bool -> Bool -> Bool
true ∨ y = true
false ∨ y = y
¬_ : Bool -> Bool
¬ true = false
¬ false = true
data List (A : Set) : Set where
nil : List A
_::_ : A -> List A -> List A
_++_ : {A : Set} -> List A -> List A -> List A
nil ++ ys = ys
(x :: xs) ++ ys = x :: xs ++ ys
filter : {A : Set} -> (A -> Bool) -> List A -> List A
filter p nil = nil
filter p (x :: xs) = if p x then x :: filter p xs else filter p xs
postulate
String : Set
Int : Set
Char : Set
{-# BUILTIN BOOL Bool #-}
{-# BUILTIN FALSE false #-}
{-# BUILTIN TRUE true #-}
{-# BUILTIN STRING String #-}
{-# BUILTIN INTEGER Int #-}
{-# BUILTIN CHAR Char #-}
{-# BUILTIN LIST List #-}
{-# BUILTIN NIL nil #-}
{-# BUILTIN CONS _::_ #-}
primitive
primStringEquality : String -> String -> Bool
_==_ = primStringEquality
infix 10 if_then_else_
infixr 50 _::_ _++_
infixl 5 _∨_
infixl 7 _∧_
infix 50 ¬_
infix 15 _==_
open Prelude
Name : Set
Name = String
data Exp : Set where
var : Name -> Exp
ƛ_⟶_ : Name -> Exp -> Exp
_$_ : Exp -> Exp -> Exp
infixl 50 _$_
infix 20 ƛ_⟶_
infix 80 _[_/_]
infix 15 _∈_
_∈_ : Name -> List Name -> Bool
x ∈ y :: ys = x == y ∨ x ∈ ys
x ∈ nil = false
-- Free variables
FV : Exp -> List Name
FV (var x) = x :: nil
FV (s $ t) = FV s ++ FV t
FV (ƛ x ⟶ t) = filter (\y -> ¬ (x == y)) (FV t)
-- Fresh names
fresh : Name -> Exp -> Name
fresh x e = fresh' (FV e)
where
fresh' : List Name -> Name
fresh' xs = "z" -- TODO
-- Substitution
_[_/_] : Exp -> Exp -> Name -> Exp
var x [ r / z ] = if x == z then r else var x
(s $ t) [ r / z ] = s [ r / z ] $ t [ r / z ]
(ƛ x ⟶ t) [ r / z ] =
if x == z then ƛ x ⟶ t
else if x ∈ FV r then ( let y : Name
y = fresh x r
in ƛ y ⟶ t [ var y / x ] [ r / z ]
)
else ƛ x ⟶ t [ r / z ]