Skip to content

PCF definitions

PCF and its denotational semantics were orginally defined by Dana Scott in 1969 (Scott 1993) with combinators (S, K) instead of λ-abstraction. Gordon Plotkin subsequently defined a denotational semantics for PCF including λ-abstraction (Plotkin 1977). This module formalises a denotational semantics of PCF in Agda, corresponding closely to Plotkin's original paper.

The following options are needed in connection with the lightweight formalisation of [function domains] in Agda.

{-# OPTIONS --rewriting --confluence-check --lossy-unification #-}

module PCF.Definitions where

open import Notation

Abstract Syntax

module Abstract-Syntax where

Types

The notation for types in (Plotkin 1977) uses the Greek letters σ and τ to range over types, ι and o for ground types (of individuals and truthvalues respectively), and (σ → τ) for function types. Agda supports mixfix notation, but ordinary arrows and parentheses are reserved symbols; the Agda formalisation of PCF types uses σ ⇒ τ instead of (σ → τ):

  data Types  : Set where                          -- type terms
    ι         : Types                              -- individuals
    o         : Types                              -- truth-values
    _⇒_       : Types  Types  Types              -- functions
  infixr 1 _⇒_
  variable σ τ : Types

As usual, σ₁ ⇒ σ₂ ⇒ τ is implicitly grouped to the right: σ₁ ⇒ (σ₂ ⇒ τ).

Variables

A variable in Vars σ is written α i σ; in (Plotkin 1977) variables are written \(\alpha_i^\sigma\), and the set of variables is not named.

The argument i merely distinguishes between variables – it is not a De Bruin index.

  open import Agda.Builtin.Nat public using (Nat)
  data Vars   : Types  Set where                  -- typed variables
    α         : Nat  (σ : Types)  Vars σ         -- α i σ is a variable of type σ
  variable i  : Nat

Constants

The PCF term language includes ℒᴬ, the set of standard constants for arithmetic, written \(\mathcal L_A\) in (Plotkin 1977).

  data ℒᴬ     : Types  Set where                  -- typed constants
    tt        : ℒᴬ o                               -- true
    ff        : ℒᴬ o                               -- false
             : ℒᴬ (o  σ  σ  σ)                 -- conditional
    Y         : ℒᴬ ((σ  σ)  σ)                   -- fixed point
    k         : Nat  ℒᴬ ι                         -- numerals
    ⦅+1⦆      : ℒᴬ (ι  ι)                         -- successor
    ⦅−1⦆      : ℒᴬ (ι  ι)                         -- predecessor
    Z         : ℒᴬ (ι  o)                         -- zero test
  variable c  : ℒᴬ σ

In (Plotkin 1977) the constants and Y are subscripted by their types; in Agda, it is simpler to leave σ as an implicit argument.

Terms

For each type σ the terms in Terms σ are intrinsically-typed: all their subterms are well-typed.

The term constructor 𝑉 below merely includes variables in terms; the constructor 𝐿 includes constants.

In Agda, mixfix notation requires arguments to be separated by characters other than spaces. Below, the notation for application ⦅ M ␣ N ⦆ and λ-abstraction ⦅λ α ␣ M ⦆ uses the Unicode character (representing a space) as a separator. Following (Plotkin 1977), both terms are parenthesised, but using ⦅…⦆ instead of ordinary parentheses.

  data Terms  : Types  Set where                  -- typed terms
    𝑉_        : Vars σ  Terms σ                   -- variable
    𝐿_        : ℒᴬ σ  Terms σ                     -- constant
    ⦅_␣_⦆     : Terms (σ  τ)  Terms σ  Terms τ  -- function application
    ⦅λ_␣_⦆    : Vars σ  Terms τ  Terms (σ  τ)   -- function abstraction
  variable M N : Terms σ

Domain equations

The domains 𝒟 σ form a standard collection of domains for arithmetic in PCF, written \(\mathcal D_\sigma\) in (Plotkin 1977).

As PCF is a simply-typed language, the domain equations do not involve recursion. Their formalisation in Agda is as ordinary type definitions, not involving bijections or embeddings.

module Domain-Equations where

  open Abstract-Syntax
  open Notation.Flat.Booleans using (Bool; Bool⊥)
  open Notation.Flat.Naturals using (Nat⊥; eqNat)
  𝒟 : Types  Domain       -- standard domains
  𝒟 ι        = Nat⊥        -- natural numbers
  𝒟 o        = Bool⊥       -- truth-values
  𝒟 (σ  τ)  = 𝒟 σ →ᶜ 𝒟 τ  -- functions
  variable x y z :  𝒟 σ 

Environments ρ are type-preserving maps from variables to values. They are naturally modeled by a dependent type: Env σ consists of type-preserving maps from variables in Vars σ to their values in the carrier of the domain 𝒟 σ. The environment ρ⊥ maps all variables to .

  Env = (σ : Types)   Vars σ →ˢ 𝒟 σ   -- typed environments
  variable ρ : Env
  ρ⊥ : Env                               -- initial environment
  ρ⊥ _ _ = 

Extension or overriding environments requires instances of the equality tests for both variables and types. The definition of the latter is somewhat tedious in Agda.

  open Notation.Flat.Booleans using (Eq; _==_)
  open Notation.Updates using (_[_/_])
  _==ⱽ_ : Vars σ  Vars σ  Bool
  open import Agda.Builtin.Nat renaming (_==_ to _==ᴺ_) public
  (α i σ ==ⱽ α i′ σ)  =  (i ==ᴺ i′)
  instance
    eqV : Eq (Vars σ)
    _==_ {{eqV}} = _==ⱽ_
  open Notation.Updates using (MaybeEq; _==?_; just; nothing; refl; _[_←_])
  instance
    eqT : MaybeEq Types
    eqT ._==?_ ι ι = just refl
    eqT ._==?_ o o = just refl
    eqT ._==?_ (σ  τ) (σ₁  τ₁) with σ ==? σ₁  | τ ==? τ₁
    eqT ._==?_ (σ  τ) (σ₁  τ₁)    | just refl | just refl = just refl
    eqT ._==?_ (σ  τ) (σ₁  τ₁)    | _         | _         = nothing
    eqT ._==?_ _ _ = nothing

The definition of ρ [ x / v ]′ is essentially the composition of two levels of extension:

  _[_/_]′ : Env   𝒟 σ   Vars σ  Env
  -- ρ [ v / x ]′ maps x to v, and other x′ to ρ x′
  _[_/_]′ {σ} ρ x v = ρ [ σ  ρ σ [ x / v ] ]

Semantic functions

module Semantic-Functions where

  open Abstract-Syntax
  open Domain-Equations

Variables

The notation ρ ⟦ α i σ ⟧ gives the value of the variable α i σ in ρ by applying ρ σ to the variable.

  _⟦_⟧ : Env  Vars σ   𝒟 σ      -- typed variable denotations
  ρ  α i σ  = ρ σ (α i σ)

Constants

The semantic function 𝒜⟦ c ⟧ gives the standard interpretation of the constant c. The corresponding definitions in (Plotkin 1977) use case analysis, which is not supported in this Agda formalisation (partly because it can express non-continuous functions).

  open Notation.Flat using (; _♯)
  open Notation.Flat.Booleans using (_⟶_,_; _==⊥_; false; true)
  open Notation.Flat.Naturals using (_+_; _-_)
  𝒜⟦_⟧ : ℒᴬ σ   𝒟 σ              -- typed constant denotations
  𝒜⟦ tt     =   true
  𝒜⟦ ff     =   false
  𝒜⟦       =  λ β δ₁ δ₂  (β  δ₁ , δ₂)
  𝒜⟦ Y      =  fix
  𝒜⟦ k n    =   n
  𝒜⟦ ⦅+1⦆   =   n   (n + 1)) 
  𝒜⟦ ⦅−1⦆   =   n   (n ==ᴺ 0)   ,  (n - 1)) 
  𝒜⟦ Z      =   n   (n ==ᴺ 0)) 

Terms

The semantic function 𝒜′⟦ M ⟧ is written \(\hat{\mathcal A} \llbracket M \rrbracket\) in (Plotkin 1977). It gives the denotation of the term M as a function of the environment ρ.

  𝒜′⟦_⟧ : Terms σ   Env →ˢ 𝒟 σ   -- typed term denotations
  𝒜′⟦ 𝑉 α i σ  ρ           =  ρ  α i σ 
  𝒜′⟦ 𝐿 c  ρ               =  𝒜⟦ c 
  𝒜′⟦  M  N   ρ         =  𝒜′⟦ M  ρ (𝒜′⟦ N  ρ) 
  𝒜′⟦ ⦅λ α i σ  M   ρ x  =  𝒜′⟦ M  (ρ [ x / α i σ ]′)

See the Tests module for some examples of abstract syntax terms and equivalence proofs.