Copyright | (c) Murdoch J. Gabbay 2020 |
---|---|
License | GPL-3 |
Maintainer | murdoch.gabbay@gmail.com |
Stability | experimental |
Portability | POSIX |
Safe Haskell | None |
Language | Haskell2010 |
Syntax and reductions of System F using the Nominal package
Synopsis
- data ATrm
- data ATyp
- type NTypLabel = String
- type NTyp = KName ATyp NTypLabel
- data Typ
- typRecurse :: (NTyp -> a) -> (Typ -> Typ -> a) -> (NTyp -> Typ -> a) -> Typ -> a
- type NTrmLabel = (String, Typ)
- type NTrm = KName ATrm NTrmLabel
- data Trm
- typeOf :: Trm -> Maybe Typ
- typeOf' :: Trm -> Typ
- typeable :: Trm -> Bool
- nf :: Trm -> Maybe Trm
- nf' :: Trm -> Trm
- normalisable :: Trm -> Bool
- class PP a where
- tall :: NTypLabel -> (Typ -> Typ) -> Typ
- tlam :: NTypLabel -> (Typ -> Trm) -> Trm
- lam :: NTrmLabel -> (Trm -> Trm) -> Trm
- (@.) :: Trm -> Trm -> Trm
- (@:) :: Trm -> Typ -> Trm
- idTrm :: Trm
- idTrm2 :: Trm
- zero :: Trm
- suc :: Trm
- one :: Trm
- nat :: Typ
- church :: Int -> Trm
- transform :: Typ
- selfapp :: Trm
Introduction
System F is a classic example and has some interesting features:
- Two kinds of variable: type variables and term variables.
- Three kinds of binding: type forall binding a type variable in a type; term lambda binding a term variable in a term; and type lambda binding a type variable in a term.
- A static assignment of semantic information to term variables, namely: a type assignment. Thus intuitively term variables carry labels (types), which themselves may contain type variables.
- And it's an expressive system of independent mathematical interest.
So implementing System F is a natural test for this package. We start with atoms:
With DataKinds
, we obtain:
ATyp
a type of atoms to identify type variables
, andNTyp
ATrm
a type of atoms to identify term variables
.NTrm
See Tom
for more discussion of how this works.
Instances
Data ATrm Source # | |
Defined in Language.Nominal.Examples.SystemF gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ATrm -> c ATrm # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c ATrm # dataTypeOf :: ATrm -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c ATrm) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ATrm) # gmapT :: (forall b. Data b => b -> b) -> ATrm -> ATrm # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> ATrm -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> ATrm -> r # gmapQ :: (forall d. Data d => d -> u) -> ATrm -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> ATrm -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> ATrm -> m ATrm # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> ATrm -> m ATrm # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> ATrm -> m ATrm # | |
PP NTrm Source # | Pretty-print term variable |
KSub NTrm Trm Trm Source # | Substitute term variable with term in term |
KSub NTyp Typ NTrm Source # | Substitute type variables with type in term variable. Non-trivial because a term variable carries a label which contains a type. Action is functorial, descending into the type label. |
With DataKinds
, we obtain:
ATyp
a type of atoms to identify type variables
, andNTyp
ATrm
a type of atoms to identify term variables
.NTrm
See Tom
for more discussion of how this works.
Instances
Data ATyp Source # | |
Defined in Language.Nominal.Examples.SystemF gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ATyp -> c ATyp # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c ATyp # dataTypeOf :: ATyp -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c ATyp) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ATyp) # gmapT :: (forall b. Data b => b -> b) -> ATyp -> ATyp # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> ATyp -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> ATyp -> r # gmapQ :: (forall d. Data d => d -> u) -> ATyp -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> ATyp -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> ATyp -> m ATyp # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> ATyp -> m ATyp # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> ATyp -> m ATyp # | |
PP NTyp Source # | Pretty-print type variable |
KSub NTyp Typ Trm Source # | |
KSub NTyp Typ NTrm Source # | Substitute type variables with type in term variable. Non-trivial because a term variable carries a label which contains a type. Action is functorial, descending into the type label. |
KSub NTyp Typ Typ Source # | Substitution acts on type variables. Capture-avoidance is automagical. |
System F types
Datatype of System F types
We use Generic
to deduce a swapping action for atoms of sorts
and ATyp
.
Just once, we spell out the definition implicit in the generic instance: ATrm
instance Swappable Typ where swpN n1 n2 (TVar n) = TVar $ swpN n1 n2 n swpN n1 n2 (t' :-> t) = swpN n1 n2 t' :-> swpN n1 n2 t swpN n1 n2 (All x) = All $ swpN n1 n2 x
This is boring, and automated, and that's the point: swappings distribute uniformly through everything including abstractors (the x
under the All
).
(The mathematical reason for this is that swappings are invertible, whereas renamings and substitutions aren't.)
Instances
Eq Typ Source # | |
Data Typ Source # | |
Defined in Language.Nominal.Examples.SystemF gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Typ -> c Typ # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Typ # dataTypeOf :: Typ -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Typ) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Typ) # gmapT :: (forall b. Data b => b -> b) -> Typ -> Typ # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Typ -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Typ -> r # gmapQ :: (forall d. Data d => d -> u) -> Typ -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Typ -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Typ -> m Typ # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Typ -> m Typ # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Typ -> m Typ # | |
Show Typ Source # | |
Generic Typ Source # | |
Arbitrary Typ Source # | For QuickCheck tests: pick a type |
Swappable Typ Source # | |
PP NTrm Source # | Pretty-print term variable |
PP Typ Source # | Pretty-print type |
KSub NTrm Trm Trm Source # | Substitute term variable with term in term |
KSub NTyp Typ Trm Source # | |
KSub NTyp Typ NTrm Source # | Substitute type variables with type in term variable. Non-trivial because a term variable carries a label which contains a type. Action is functorial, descending into the type label. |
KSub NTyp Typ Typ Source # | Substitution acts on type variables. Capture-avoidance is automagical. |
Show (Maybe Typ) Source # | |
type Rep Typ Source # | |
Defined in Language.Nominal.Examples.SystemF type Rep Typ = D1 (MetaData "Typ" "Language.Nominal.Examples.SystemF" "nom-0.1.0.1-3UtpNOnqRlSC6EhVIia7SR" False) (C1 (MetaCons "TVar" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 NTyp)) :+: (C1 (MetaCons ":->" (InfixI LeftAssociative 9) False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 Typ) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 Typ)) :+: C1 (MetaCons "All" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (KAbs NTyp Typ))))) |
System F terms
System F terms.
- We get swapping actions automatically, and also substitution of type names
NTyp
for typesTyp
. - Substitution of term variables
NTrm
for termsTrm
needs defined separately.
Var NTrm | Term variable, labelled by its display name and type |
App Trm Trm | Apply a term to a term |
Lam (KAbs NTrm Trm) | Nominal atoms-abstraction by a term variable. |
TApp Trm Typ | Apply a term to a type |
TLam (KAbs NTyp Trm) | Nominal atoms-abstraction by a type variable. |
Instances
Normal forms
normalisable :: Trm -> Bool Source #
True if term is normalisable; false if not.
Pretty-printer
Typeclass for things that can be pretty-printed
Helper functions for building terms
tall :: NTypLabel -> (Typ -> Typ) -> Typ Source #
Build type quantification from function: f ↦ ∀ a.(f a) for fresh a
tlam :: NTypLabel -> (Typ -> Trm) -> Trm Source #
Build type lambda from function: f ↦ Λ a.(f a) for fresh a
lam :: NTrmLabel -> (Trm -> Trm) -> Trm Source #
Build term lambda from function: f ↦ λ a.(f a) for fresh a
Example terms
Tests
Property-based tests are in Language.Nominal.Properties.Examples.SystemFSpec.