Copyright | (c) Murdoch J. Gabbay 2020 |
---|---|
License | GPL-3 |
Maintainer | murdoch.gabbay@gmail.com |
Stability | experimental |
Portability | POSIX |
Safe Haskell | None |
Language | Haskell2010 |
The basic framework: a nominal theory of names and swappings
Synopsis
- newtype KAtom s = Atom Unique
- type Atom = KAtom Tom
- data Tom
- atTom :: Proxy Tom
- freshKAtomsIO :: Traversable m => m a -> IO (m (KAtom s))
- freshAtomsIO :: Traversable m => m a -> IO (m Atom)
- freshKAtomIO :: IO (KAtom s)
- freshAtomIO :: IO Atom
- class Swappable a where
- swp :: Swappable a => Atom -> Atom -> a -> a
- type KPerm s = [(KAtom s, KAtom s)]
- type Perm = KPerm Tom
- perm :: (Typeable s, Swappable a) => KPerm s -> a -> a
- data KName s t = Name {}
- type Name = KName Tom
- withLabel :: KName s t -> t -> KName s t
- withLabelOf :: KName s t -> KName s t -> KName s t
- justALabel :: t -> KName s t
- justAnAtom :: KAtom s -> KName s t
- kswpN :: (Typeable s, Swappable a) => KName s t -> KName s t -> a -> a
- swpN :: Swappable a => Name t -> Name t -> a -> a
- newtype Nameless a = Nameless {
- getNameless :: a
Documentation
An atom is a unique atomic token.
The argument s
of KAtom
is part of facilities offered by this package for declaring types of atom s
ranging over kinds k
. For usage see ATyp
, and ATrm
in Language.Nominal.Examples.SystemF.
If your development requires just a single type of atomic tokens, ignore KAtom
and use KAtom
.
Instances
(Typeable s, Typeable t) => KSupport s (KAtom t) Source # | |
(Typeable s, Typeable t) => KUnifyPerm s (KAtom t) Source # | Unify atoms |
Eq (KAtom s) Source # | |
Data s => Data (KAtom s) Source # | |
Defined in Language.Nominal.Name gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> KAtom s -> c (KAtom s) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (KAtom s) # toConstr :: KAtom s -> Constr # dataTypeOf :: KAtom s -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (KAtom s)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (KAtom s)) # gmapT :: (forall b. Data b => b -> b) -> KAtom s -> KAtom s # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> KAtom s -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> KAtom s -> r # gmapQ :: (forall d. Data d => d -> u) -> KAtom s -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> KAtom s -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> KAtom s -> m (KAtom s) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> KAtom s -> m (KAtom s) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> KAtom s -> m (KAtom s) # | |
Ord (KAtom s) Source # | |
Show (KAtom s) Source # | Display an atom by showing (the hash of) its unique id. |
Generic (KAtom s) Source # | |
Arbitrary (KAtom s) Source # | Pick an atom |
Typeable s => Swappable (KAtom s) Source # | Base case for swapping: atoms acting on atoms. |
SMonad [KAtom s] (KNom s) Source # | |
(Typeable s, Swappable a) => Binder (KNom s a) [KAtom s] a s Source # | Acts on a |
(Typeable s, Swappable a, KRestrict s a) => BinderConc (KNom s a) [KAtom s] a s () Source # | Suppose we have a nominal abstraction cnoc () = unNom |
(Typeable s, Swappable a) => BinderConc (KNom s a) [KAtom s] a s [KAtom s] Source # | Concrete a nominal abstraction at a particular list of atoms. Dangerous for two reasons:
|
(Typeable s, Swappable a) => BinderConc (KNom s a) [KAtom s] a s (Proxy s) Source # | Suppose we have a nominal abstraction cnoc (Proxy :: Proxy s) = exit |
Validator r d v => Binder (Chunk r d v) [Atom] [Transaction r d v] Tom Source # | Acts on a |
type Rep (KAtom s) Source # | |
Defined in Language.Nominal.Name |
We provide a stock datatype
. Tom
Using the DataKinds
package, this is then used to provide a stock type of atoms
. KAtom
Instances
A proxy element for sort
. If we pass this, we tell the typechecker we are "at Tom".Tom
Creating atoms
freshKAtomsIO :: Traversable m => m a -> IO (m (KAtom s)) Source #
Make a fresh atom for each element of some list (a
ny list). If you just want one fresh atom, use e.g. [()]
.
This is an IO action; when executed, fresh identifiers get generated.
freshAtomsIO :: Traversable m => m a -> IO (m Atom) Source #
Make a fresh atom at
for each element of some list (Tom
a
ny list).
freshKAtomIO :: IO (KAtom s) Source #
For convenience: generate a fresh katom
freshAtomIO :: IO Atom Source #
For convenience: generate a fresh atom
>>>
a <- freshAtomIO
>>>
b <- freshAtomIO
>>>
a == b
False
Atom swapping
class Swappable a where Source #
Types that admit a swapping action.
A swapping (a b)
maps
a
tob
andb
toa
and- any other
c
toc
.
Swappings are invertible, which allows them to commute through type-formers containing negative arities, e.g. the left-hand argument of function arrow. Swappings always distribute:
swp a b (x, y) == (swp a b x, swp a b y) swp a b [x1, x2, x3] == [swp a b x1, swp a b x2, swp a b x3] swp a b (f x) == (swp a b f) (swp a b x) swp a b (abst n x) == abst (swp a b n) (swp a b x) swp a b (res [n] x) == res [swp a b n] (swp a b x) swp a b (Name t x) == Name (swp a b t) (swp a b x)
Technical note: The content of Swappable a
is that a
supports a swapping action by atoms of every s
. Everything else, e.g. KSupport
, just uses s
. So k
is a "world" of sorts of atoms, for a particular application.
This is invisible at our default world
because Tom
has only one inhabitant, Tom
'
. See Tom
ASort
and surrounding code for a more sophisticated atoms setup.
Nothing
kswp :: Typeable s => KAtom s -> KAtom s -> a -> a Source #
kswp :: (Typeable s, Generic a, GSwappable (Rep a)) => KAtom s -> KAtom s -> a -> a Source #
Instances
Swappable Bool Source # | |
Swappable Char Source # | |
Swappable Int Source # | |
Swappable () Source # | |
Swappable Exp Source # | |
Swappable Trm Source # | |
Swappable Typ Source # | |
Swappable Prog Source # | |
Swappable Operand Source # | |
Swappable Prog Source # | |
Swappable Operand Source # | |
Swappable a => Swappable [a] Source # | |
Swappable a => Swappable (Maybe a) Source # | |
Swappable a => Swappable (NonEmpty a) Source # | |
(Ord a, Swappable a) => Swappable (Set a) Source # | |
Swappable (Nameless a) Source # | |
Typeable s => Swappable (KAtom s) Source # | Base case for swapping: atoms acting on atoms. |
Swappable a => Swappable (BinderSupp a) Source # | |
Defined in Language.Nominal.Binder kswp :: Typeable s => KAtom s -> KAtom s -> BinderSupp a -> BinderSupp a Source # | |
Typeable s => Swappable (KRen s) Source # | |
Swappable r => Swappable (Input r) Source # | |
(Swappable a, Swappable b) => Swappable (a -> b) Source # | Swap distributes over function types, because functions inherit swapping action pointwise (also called the conjugation action) |
(Swappable a, Swappable b) => Swappable (Either a b) Source # | |
(Swappable a, Swappable b) => Swappable (a, b) Source # | |
(Swappable a, Swappable b, Ord a) => Swappable (Map a b) Source # | Swap distributes over map types. Note that maps store their keys ordered for quick lookup, so a swapping acting on a map is not a noop and can provoke reorderings. |
(Typeable s, Swappable t) => Swappable (KName s t) Source # | Swapping atoms in names distributes normally; so we swap in the semantic label and also in the name's atom identifier. Operationally, it's just a tuple action: swp atm1 atm2 (Name t atm) = Name (swp atm1 atm2 t) (swp atm1 atm2 atm) |
(Swappable i, Swappable a) => Swappable (XSuspend i a) Source # | |
(Typeable s, Swappable a) => Swappable (KNom s a) Source # | Swap goes under name-binders. swp n1 n2 (ns @> x) = (swp n1 n2 ns) @> (swp n1 n2 x) |
(Swappable n, Swappable a) => Swappable (KAbs n a) Source # | Spelling out the generic swapping action for clarity, where we write |
Swappable (ValFin r d) Source # | |
Swappable (Val r d) Source # | |
Swappable (ValTriv r d) Source # | |
(Swappable d, Swappable v) => Swappable (Output d v) Source # | |
(Swappable a, Swappable b, Swappable c) => Swappable (a, b, c) Source # | |
Swappable a => Swappable (KEvFinMap s a b) Source # | |
(Typeable s, Swappable a, Swappable b) => Swappable (KEvFun s a b) Source # | |
(Swappable r, Swappable d, Swappable v) => Swappable (Blockchain r d v) Source # | |
Defined in Language.Nominal.Examples.IdealisedEUTxO kswp :: Typeable s => KAtom s -> KAtom s -> Blockchain r d v -> Blockchain r d v Source # | |
(Swappable r, Swappable d, Swappable v) => Swappable (Chunk r d v) Source # | |
(Swappable r, Swappable d, Swappable v) => Swappable (Context r d v) Source # | |
(Swappable r, Swappable d, Swappable v) => Swappable (Transaction r d v) Source # | |
Defined in Language.Nominal.Examples.IdealisedEUTxO kswp :: Typeable s => KAtom s -> KAtom s -> Transaction r d v -> Transaction r d v Source # | |
(Swappable a, Swappable b, Swappable c, Swappable d) => Swappable (a, b, c, d) Source # | |
(Swappable a, Swappable b, Swappable c, Swappable d, Swappable e) => Swappable (a, b, c, d, e) Source # | |
Permutations
type KPerm s = [(KAtom s, KAtom s)] Source #
A permutation represented as a list of swappings (simple but inefficient).
perm :: (Typeable s, Swappable a) => KPerm s -> a -> a Source #
A permutation acts as a list of swappings. Rightmost/innermost swapping acts first.
>>>
a <- freshAtomIO
>>>
b <- freshAtomIO
>>>
c <- freshAtomIO
>>>
perm [(c,b), (b,a)] a == c
True
Names
A name is a pair of
- an atom, and
- a label
t
.
t
is intended to store semantic information about the atom. For instance, if implementing a simply-typed lambda-calculus then t
might be a dataype of (object-level) types.
A similar effect could be achieved by maintaining a monadic lookup context relating atoms to their semantic information; the advantage of using a name is that this information is packaged up with the atom in a local datum of type
. KName
Instances
PP NTrm Source # | Pretty-print term variable |
PP NTyp Source # | Pretty-print type variable |
KSub Var Exp Exp Source # | Substitution. Capture-avoidance is automatic. |
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. |
KSub V Operand Prog Source # | Substitution on |
KSub V Operand Operand Source # | Substitution as standard on |
KSub V Operand Prog Source # | Substitution on |
KSub V Operand Operand Source # | Substitution as standard on |
(Typeable s, Typeable u, KSupport s t) => KSupport s (KName u t) Source # | |
(KSupport s a, KSupport s t) => KSupport s (KAbs (KName s t) a) Source # | Support of a :@> x is the support of x minus a |
(Typeable s, KUnifyPerm s t, KUnifyPerm s a) => KUnifyPerm s (KAbs (KName s t) a) Source # | Unify |
(Typeable s, Typeable u, KUnifyPerm s t) => KUnifyPerm s (KName u t) Source # | Unify names: they behave just an atom-label tuple |
Functor (KName s) Source # | |
Default t => Applicative (KAbs (KName s t)) Source # | |
Defined in Language.Nominal.Abs pure :: a -> KAbs (KName s t) a # (<*>) :: KAbs (KName s t) (a -> b) -> KAbs (KName s t) a -> KAbs (KName s t) b # liftA2 :: (a -> b -> c) -> KAbs (KName s t) a -> KAbs (KName s t) b -> KAbs (KName s t) c # (*>) :: KAbs (KName s t) a -> KAbs (KName s t) b -> KAbs (KName s t) b # (<*) :: KAbs (KName s t) a -> KAbs (KName s t) b -> KAbs (KName s t) a # | |
Foldable (KName s) Source # | |
Defined in Language.Nominal.Name fold :: Monoid m => KName s m -> m # foldMap :: Monoid m => (a -> m) -> KName s a -> m # foldr :: (a -> b -> b) -> b -> KName s a -> b # foldr' :: (a -> b -> b) -> b -> KName s a -> b # foldl :: (b -> a -> b) -> b -> KName s a -> b # foldl' :: (b -> a -> b) -> b -> KName s a -> b # foldr1 :: (a -> a -> a) -> KName s a -> a # foldl1 :: (a -> a -> a) -> KName s a -> a # elem :: Eq a => a -> KName s a -> Bool # maximum :: Ord a => KName s a -> a # minimum :: Ord a => KName s a -> a # | |
Traversable (KName s) Source # | |
Arbitrary (Name String) Source # | |
Eq (KName s t) Source # | Names are equal when they refer to the same atom. WARNING: Labels are not considered!
In particular, |
(Typeable s, Swappable t, Eq t, Eq a) => Eq (KAbs (KName s t) a) Source # | Abstractions are equal up to fusing their abstracted names. |
(Data s, Data t) => Data (KName s t) Source # | |
Defined in Language.Nominal.Name gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> KName s t -> c (KName s t) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (KName s t) # toConstr :: KName s t -> Constr # dataTypeOf :: KName s t -> DataType # dataCast1 :: Typeable t0 => (forall d. Data d => c (t0 d)) -> Maybe (c (KName s t)) # dataCast2 :: Typeable t0 => (forall d e. (Data d, Data e) => c (t0 d e)) -> Maybe (c (KName s t)) # gmapT :: (forall b. Data b => b -> b) -> KName s t -> KName s t # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> KName s t -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> KName s t -> r # gmapQ :: (forall d. Data d => d -> u) -> KName s t -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> KName s t -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> KName s t -> m (KName s t) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> KName s t -> m (KName s t) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> KName s t -> m (KName s t) # | |
Ord (KName s t) Source # | Names are leq when their atoms are leq. WARNING: Labels are not considered!
In particular, |
Defined in Language.Nominal.Name | |
Show (KName s ()) Source # | |
Show t => Show (KName s t) Source # | |
(Typeable s, Swappable t, Swappable a, Show t, Show a) => Show (KAbs (KName s t) a) Source # | We show an abstraction by evaluating the function inside |
Generic (KName s t) Source # | |
Arbitrary a => Arbitrary (KName s a) Source # | |
(Typeable s, Swappable t, Swappable a, Arbitrary (KName s t), Arbitrary a) => Arbitrary (KAbs (KName s t) a) Source # | |
(Typeable s, Swappable t) => Swappable (KName s t) Source # | Swapping atoms in names distributes normally; so we swap in the semantic label and also in the name's atom identifier. Operationally, it's just a tuple action: swp atm1 atm2 (Name t atm) = Name (swp atm1 atm2 t) (swp atm1 atm2 atm) |
(Typeable s, Typeable u, KSub (KName s n) x t, KSub (KName s n) x y, Swappable t, Swappable y) => KSub (KName s n) x (KAbs (KName u t) y) Source # | sub on a nominal abstraction substitutes in the label, and substitutes capture-avoidingly in the body |
(Typeable s, Swappable t, Swappable a) => Binder (KAbs (KName s t) a) (KName s t) a s Source # | Acts on an abstraction |
(Typeable s, Swappable n, Swappable x, Swappable y, KSub (KName s n) x y) => BinderConc (KAbs (KName s n) y) (KName s n) y s x Source # | Nameless form of substitution, where the name for which we substitute is packaged in a |
KSub (KName s n) (KName s n) (KName s n) Source # | sub on names |
type Rep (KName s t) Source # | |
Defined in Language.Nominal.Name type Rep (KName s t) = D1 (MetaData "KName" "Language.Nominal.Name" "nom-0.1.0.1-3UtpNOnqRlSC6EhVIia7SR" False) (C1 (MetaCons "Name" PrefixI True) (S1 (MetaSel (Just "nameLabel") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 t) :*: S1 (MetaSel (Just "nameAtom") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (KAtom s)))) |
withLabelOf :: KName s t -> KName s t -> KName s t Source #
Overwrite the name's label. Intended to be read infix as n `withLabelOf n'
justALabel :: t -> KName s t Source #
Name with
atom, so really just a label. Use with care!undefined
justAnAtom :: KAtom s -> KName s t Source #
Name with
label, so really just an atom. Use with care!undefined
Name swapping
kswpN :: (Typeable s, Swappable a) => KName s t -> KName s t -> a -> a Source #
A name swap discards the names' labels and calls the atom-swap
.kswp
Nameless types
Some types, like
and Bool
, are String
. E.g. if we have a truth-value, we know it doesn't have any names in it; we might have used names to calculate the truth-value, but the truth-value itself Nameless
or True
is nameless. False
Nameless | |
|
Instances
KSub n x (Nameless a) Source # | sub on nameless type is trivial |
Typeable s => KRestrict s (Nameless a) Source # | Restriction is trivial on elements of nameless types |
Typeable s => KSupport s (Nameless a) Source # | |
(Typeable s, Eq a) => KUnifyPerm s (Nameless a) Source # | |
Eq a => Eq (Nameless a) Source # | |
Ord a => Ord (Nameless a) Source # | |
Read a => Read (Nameless a) Source # | |
Show a => Show (Nameless a) Source # | |
Swappable (Nameless a) Source # | |
Tests
Property-based tests are in Language.Nominal.Properties.NameSpec.